Django View with two Slugs - python-3.x

How to write a Django View with two slugs?
Each slug is from different Models.
I want to get www.example.com/category/slug1/slug2
Please provide an example code.
Views.py
class SubjectDetailView(generic.DetailView, SingleObjectMixin):
model = Programmesearch
template_name = 'mnsdirectory/subject_detail.html'
slug_field = 'subjectslug'
slug_url_kwarg = 'subjectslug'
Urls.py
app_name = 'mnsdirectory'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'), #views.indexSubjectDetailView(View)
path('study/<slug:subjectslug>/', views.SubjectDetailView.as_view(), name='subject-detail'),
path('study-abroad/<slug:studylevelslug>/', views.StudylevelDetailView.as_view(), name='studylevel-list'),
]
Models.py:
class Programmesearch(models.Model):
full_subject_name = models.CharField(max_length=100, blank=False, null=False)
subjectslug = models.SlugField(unique=True, editable=False, max_length=100)
class StudyLevel(models.Model):
study_level = models.CharField(max_length=100, blank=False, null=False)
studylevelslug = models.SlugField(unique=True, editable=False, max_length=100)

good first that my advice personally is that you have to have a good base of POO PYTHON and know well the MVT architecture, Django works a very similar architecture the MVC model view controller, now in View it goes all the logical part of python and there is where we will declare or whether we are going to end in which Template we are going to paint data processed by VIEW-Server.
Well, first of all how you want to work with those 2 models what we will do is the following:
We import the following methods
from django.shortcuts import render
from django.http import HttpResponse
from django.views.generic import View
class SubjectDetailView(View):
def get(self, request, *args, **kwargs):
queryset = Programmesearch.objects.all()
return render(request, 'mnsdirectory/subject_detail.html', {'element':queryset})
finally simply in the url you place this:
path('study/slug1/slug2/', views.SubjectDetailView.as_view(), name='subject-detail'),

perfect then send to the temple a dictionary a little more complex with 2 keys:
class SubjectDetailView(View):
def get(self, request, *args, **kwargs):
queryset = Programmesearch.objects.all()
queryset2 = StudyLevel.objects.all()
return render(request, 'mnsdirectory/subject_detail.html', {'element':queryset,'element2':queryset2})

#ulvi-damirli. You can use your urls.py like this:
Urls.py
re_path(r'^(?P<slug>[\w_-]+)/(?P<studylevel>[\w_-]+)/$',
views.SubjectDetailView.as_view(), name='subject-detail'),
and in your views.py, you can catch these slugs like this:
Views.py
class SubjectDetailView(generic.DetailView, SingleObjectMixin):
model = Programmesearch
template_name = 'mnsdirectory/subject_detail.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# subjectslug = self.object.slug # Not necessary since It's a DetailView
studyLevel = StudyLevel.objects.filter(
study_level=self.kwargs.get('studylevel', None))
Hope I helped you, let me know if It worked

Related

NOT NULL constraint failed: jobs_job.created_by_id IntegrityError at /jobs/add/

I am trying to enable the user to be able to add job and after filling the form i got that error. Here is my code:
models.py
from django.db import models
from django.contrib.auth.models import User
class Job(models.Model):
title = models.CharField(max_length=255)
short_description = models.TextField()
long_description = models.TextField(blank=True, null=True)
created_by = models.ForeignKey(User, related_name='jobs', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
changed_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
views.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .forms import AddJobForm
from .models import Job
def job_detail(request, job_id):
job = Job.objects.get(pk=job_id)
return render(request, 'jobs/job_detail.html', {'job': job})
#login_required
def add_job(request):
if request.method == 'POST':
form = AddJobForm(request.POST)
if form.is_valid():
job = form.save(commit=True)
job.created_by = request.user
job.save()
return redirect('dashboard')
else:
form = AddJobForm()
return render(request, 'jobs/add_job.html', {'form': form})
forms.py
from django import forms
from .models import Job
class AddJobForm(forms.ModelForm):
class Meta:
model = Job
fields = ['title','short_description','long_description']
What do i need to do to solve this error? I have try to remove the commit=True, from views.py and I have try to remove sqlite3 and do the migrations again.
You are trying to save the object without a value for created_by (hence the error message), then assign a value for that field and save again. You should change
job = form.save(commit=True)
to
job = form.save(commit=False)
so that the first .save doesn't actually try to commit anything to the database. It is simply used to construct the Job instance so that you can complete any missing values and actually save it using job.save().
Note that if you omit the commit= argument it is assumed to be True.

Django Rest Framework to return desired results from two models

I have two models (customer, movie) and I would like to return (movie_name, customer_name, id) when I hit the URL (api/customer/1) and when I hit the URL (api/customer/1/movies) just wanted the movie names alone. How can we achieve this ?
models.py
class Customer(models.Model):
name = models.CharField(max_length=200, null=True)
class Movie(models.Model):
movie_name = models.CharField(max_length=200, null=True)
customer = models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL)
serializers.py
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customer
fields = ('id', 'name')
class MovieSerializer(serializers.ModelSerializer):
class Meta:
model = Movie
fields = '__all__'
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^api/customers/$', CustomerSerializer.as_view(), name='customers'),
]
Note:
At the moment, when I hit the URL (api/customers) it returns the id, name of all the customers. Now, I would like to know, when I hit the URL (api/customer/1) how to list the same information along with movie names and when I hit the URL (api/customer/1/movies) how to just return the movie names alone?
You will have to write two urls for this purpose but you can do this with one view and serializer like this
Urls
urlpatterns = [
path('admin/', admin.site.urls),
path('api/customers/<int:id>/', CustomerMovieView.as_view(check=True)),
path('api/customers/<int:id>/movies/', CustomerMovieView.as_view(check=False)),
]
Views and Serializers
from rest_framework import generics, response, serializer
class MovieSerializer(serializers.ModelSerializer):
customer_name = serializers.SerializerMethodField()
def get_customer_name(self, instance):
return instance.customer.name
class Mete:
model = Movie
fields = '__all__'
def to_representation(self, instance):
data = super().to_representation(instance)
if not self.context('check'):
data.pop('customer_name', None)
data.pop('customer', None)
return data
class CustomerMovieView(generics.GenericAPIView):
serializer_class = MovieSerializer
check = True
def get_serializer_context(self):
context = super().get_serializer_context()
context.update({'check': self.check})
return context
def get(self, request, *args, **kwargs):
id = kwargs.get('id')
movie = Movie.objects.get(id=id)
serialized = self.get_serializer(movie)
return response.Respoonse(serialized.data)

how to add a method to a class template view

happy new year everyone...I am new to django and i am working on a project a resume page i need help with the contact me section, i want to do something i seen in a video https://www.youtube.com/watch?v=w4ilq6Zk-08. The book i used to learn only uses class to view templates. below is my code
from django.views.generic import TemplateView
from django.shortcuts import render
# Create your views here.
class ProfilePageView(TemplateView):
template_name = 'femi_profile.html'
def contact(request):
if request.method == "POST":
name = request.POST['name']
email = request.POST['email']
subject = request.POST['subject']
message = request.POST['message']
return render(request, 'femi_profile.html', {'contact_name': name})
else:
return render(request, 'femi_profile.html', {})
After reading the django documentation https://docs.djangoproject.com/en/3.1/topics/class-based-views/intro/ once more and trying different lines of code i finally got that run and i am not asking why is it runing? i figured out how to go about this.
find the correct code below
from django.views.generic import TemplateView
from django.shortcuts import render
# Create your views here.
class ProfilePageView(TemplateView):
template_name = 'femi_profile.html'
def get(self, request, *args, **kwargs):
return render(request, self.template_name, {})
def post(self, request, *args, **kwargs):
if request.method == "POST":
name = request.POST['name']
email = request.POST['email']
subject = request.POST['subject']
message = request.POST['message']
return render(request, self.template_name, {'contact_name': name})

How to join two tables in django and serialize the same using one serializer?

I have been learning django and django rest framework since couple of weeks and I want to figure out how can I join two tables and serialize the data of same to return the json response using django rest framework.
I want to return result as json response:
{ 'user_id_id': 1, 'request_msg': 'Hi', 'response_msg': "Hi, Welcome" }
where result is
from django.db import connection
cursor = connection.cursor()
con = cursor.execute("SELECT backend_request_messages.user_id_id, backend_request_messages.request_msg as request_msg,backend_response_messages.response_msg as response_msg FROM backend_request_messages,backend_response_messages Where backend_request_messages.user_id_id=backend_response_messages.user_id_id=1 ")
Here is what I have tried :
#backend/Models.py
class User(models.Model):
username = models.CharField(max_length=50)
name = models.CharField(max_length=50, blank=True, null=True)
uid = models.CharField(max_length=12, blank=True, null=True)
age = models.CharField(max_length=3, blank=True, null=True)
active = models.BooleanField(default=True)
class Meta:
default_related_name = 'users'
def __str__(self):
return self.name
class Request_Messages(models.Model):
request_msg = models.CharField(max_length=100)
request_msg_created_at = models.DateTimeField(auto_now_add=True)
user_id = models.ForeignKey(
User, on_delete=models.CASCADE, null=True)
class Meta:
default_related_name = 'request_messages'
def __str__(self):
return self.request_msg
class Response_Messages(models.Model):
response_msg = response_msg = models.CharField(max_length=400)
response_msg_created_at = models.DateTimeField(auto_now_add=True)
user_id = models.ForeignKey(
User, on_delete=models.CASCADE, null=True)
class Meta:
default_related_name = 'response_messages'
def __str__(self):
return self.response_msg
#backend/serializers.py
class ListSerializer (serializers.Serializer):
user_id_id = serializers.IntegerField()
request_msg = serializers.CharField(max_length=100)
# request_msg_created_at = serializers.DateTimeField(read_only=True)
response_msg = serializers.CharField()
# response_msg_created_at = serializers.DateTimeField(read_only=True)
#backend/views.py
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Response_Messages, Request_Messages, User
from .serializers import ListSerializer
from django.db import connection
#api_view(['GET', 'POST'])
def chatbot(request):
if request.method == 'GET':
cursor = connection.cursor()
query_set = cursor.execute("SELECT backend_request_messages.user_id_id, backend_request_messages.request_msg as request_msg,backend_response_messages.response_msg as response_msg FROM backend_request_messages,backend_response_messages Where backend_request_messages.user_id_id=backend_response_messages.user_id_id=1 ")
columns = [column[0] for column in query_set.description]
results = []
for row in query_set.fetchall():
results.append(dict(zip(columns, row)))
serializer = ListSerializer(results)
return Response(serializer.data)
About serializers, You should refer to the docs (they're awesome and explain it best).
To give you a direction, I like to create a serializer for every model and if it's related to another model, I refer that in serializer, that way, You can easily customize behavior for each model (although not the only way at all).
So, about serializing I would do the following (notice my comments as well):
from django.contrib.auth.models import User
class User(User):
# Your user class, except, it should inherit Django's User/AbstractUser class.
class RequestMessages(models.Model):
request_msg = models.CharField(max_length=100)
request_msg_created_at = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(
User, on_delete=models.CASCADE, null=True, related_name='requests_msg')
# NOTICE THE NEW RELATED NAME, WE'LL USE IT LATER.
class Meta:
default_related_name = 'request_messages'
def __str__(self):
return self.request_msg
class ResponseMessages(models.Model):
response_msg = response_msg = models.CharField(max_length=400)
response_msg_created_at = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, related_name='responses_msg')
def __str__(self):
return self.response_msg
class RequestMsgSerializer(serializers.ModelSerializer):
# Specify what ever you like...
class Meta:
model = RequestMessages
fields = # Whatever you like to serialize.
class ResponseMsgSerializer(serializers.ModelSerializer):
class Meta:
model = ResponseMessages
fields = # Whatever you want serialized.
class UserSerializer(serializers.ModelSerializer):
# Using required = False will cause that every time you create a user they don't have to own messages.
requests_msg = RequestMsgSerializer(many=False, required=False)
responses_msg = ResponseMsgSerializer(many=False, required=False)
class Meta:
model = User
field = # Same as above ..
About your query, using raw SQL in Django is rear, usually, in most cases the Django built-in ORM will do the job and usually faster and better than you.
In your case, if you'll call your query like this for exmaple:
query_set = User.objects.filter(user=request.user)
the QuerySet object created will hit the DB one for the user object and X queries for all the associated messages with said user, so expensive.
But no need for a custom query with joins and stuff like that, Django has prefetch_related and select_related.
exmaple:
query_set = User.objects.filter(user=request.user).prefetch_related('requests_msg')
will reduce all the queries made for request messages associated to a user to only one!
Recap:
I wrote a lot because I'm still learning this stuff myself self and if you teach others you got it!
Refer to DRF's docs about serializers (there's even a dedicated section for nested serializers) and API Views, they really great.
Refer to Django's docs about prefetch related, select related and queries in general, again, Amazing docs that cover everything.
Don't just copy my code or anyone else's, there's no problem with that, just make sure you understand it first if not, you're bound to get stuck with it again!

How can I list all the nodes in my database?

I'm trying to create a simple model Node and a simple web page that shows all of my nodes in a list. But it seems not working and everytime I change the code I got a new error. So I gave up and came to here.This is what I did:
I created a Node model:
class Node(models.Model):
ID = models.DecimalField(max_digits=9, decimal_places=6)
nb_solenoid = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
connexion = models.CharField(max_length=255)
def get_absolute_url(self):
return reverse("node:index", kwargs={"id": self.id})
with this form:
class NodeForm(forms.ModelForm):
ID = forms.DecimalField(initial=0)
nb_solenoid = forms.DecimalField(initial=1)
connexion = forms.CharField(required=False,
widget=forms.Textarea(
attrs={
"placeholder": "type of connexion"
}))
class Meta:
model = Node
fields = [
'ID',
'nb_solenoid',
'connexion'
]
And this is my views.py:
def index(request):
queryset = Node.objects.all()
context = {
"object_list": queryset
}
return render(request, "node/index.html", context)
This is my code in urls.py:
urlpatterns = [path('', views.index, name='index')]
When I call this url: http://localhost:8000/node I get this error now:
NoReverseMatch at /node
Reverse for 'index' with keyword arguments '{'id': 1}' not found. 1 pattern(s) tried: ['node$']
What is a NoReverseMatch error and how do I fix my problem? Let me say that I'm a Django beginner developer.
Thank you.
The issue is that your named url path node:index takes no arguments (presumably because that view is just listing out all the nodes, not a specific node), yet your model's get_absolute_url is trying to reverse the pattern with a kwarg of id. The core problem is your get_absolute_url method; however, you really probably also would benefit from just using class based generic views:
urls.py:
urlpatterns = [
path('nodes/', NodeList.as_view(), name="node-list"),
path('node/<id>/', NodeDetail.as_view(), name="node-detail")
]
view.py:
from django.views.generic import ListView, DetailView
from .models import Node
class NodeList(ListView):
model = Node
class NodeDetail(DetailView):
model = Node
models.py:
class Node(models.Model):
<snip>
def get_absolute_url(self):
return reverse("node-detail", kwargs={"id": self.id})
I really should have mentioned, documentation for class based generic views are at: https://docs.djangoproject.com/en/2.1/topics/class-based-views/generic-display/

Resources