How can I list all the nodes in my database? - python-3.x

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/

Related

Why django-rest-framework is generating same api url for two views (both views having same queryset)?

My Project Configuration is this. This is realated to Contact Form. Here I have two approach: Customer from frontend can only post (i.e. send message) and admin can only retrieve and list the contacts.
Models.py
class Contact(models.Model):
full_name = models.CharField(max_length=100)
email = models.EmailField()
phone_no = models.CharField(max_length=10, validators=[validate_phone_no])
message = models.TextField()
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
def __str__(self):
return self.email
serializers.py
class ContactSerializer(serializers.ModelSerializer):
class Meta:
model = Contact
fields = [
'full_name',
'email',
'phone_no',
'message',
]
Views.py
class ContactViewset(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
queryset = Contact.objects.all()
search_fields = []
ordering_fields = []
ordering = []
http_method_names = ["options", "head", "get"]
serializer_class = ContactSerializer
class CustomerContactViewSet(viewsets.ModelViewSet):
permission_classes = [AllowAny]
queryset = Contact.objects.all()
http_method_names = ['post']
serializer_class = ContactSerializer
urls.py
router.register("contacts-detail", ContactViewset)
router.register("contact-form", CustomerContactViewSet)
My question is: Why DRF is generating the same url for both views although I have given different names for both:
'contact-form'----> for posting and
'contact-detail'--------> for listing the contacts
Both views are pointing to same Model - Is this the Reason?
Click Here to see generated api url
See last urls are same: and redirecting to "contact-form". and I know I can give base_name to seperate both.
But I wanted to know the mechanism behind generating same url:
If anyone could explain this? Clearly
The problem is with the way you have defined the router.register calls in your urls.py file.
The first argument of the router.register function is the base name for the viewset. This base name is used to generate the URL patterns for the viewset. If you use the same base name for multiple viewsets, then the router will generate the same URL pattern for both viewsets.
For example, in your code you have defined the following lines:
router.register("contacts-detail", ContactViewset)
router.register("contact-form", CustomerContactViewSet)
Here, you have used the base name "contacts-detail" for the ContactViewset and the base name "contact-form" for the CustomerContactViewSet. This will result in two different URL patterns being generated:
/contacts-detail/
/contact-form/
However, since both viewsets are using the same model (Contact), the router will generate the same set of URL patterns for both viewsets. This is why you are seeing the same URL patterns for both viewsets in your API.
To fix this problem, you can use different base names for the two viewsets. For example, you could use "contacts" for the ContactViewset and "customer-contacts" for the CustomerContactViewSet. This would result in the following URL patterns being generated:
/contacts/
/customer-contacts/

List Class View didn't return an HttpResponse

I've been trying to get a class-based list view to display all entries under a user's account (applicant), but when loading the page I'm given the following error:
The view jobassessment.views.view didn't return an HttpResponse object. It returned None instead.
To me that sounds like the URL dispatcher isn't running the correct view, but this is my URL file for both the whole site and the jobassessment application and I can't seem to spot the fault.
Site URL.py:
urlpatterns = [
path('admin/', admin.site.urls, name="admin"),
path('accounts/', include('django.contrib.auth.urls'), name="accounts"),
path('applicant/', include('userprofile.urls'), name="applicant"),
path('assessments/', include('jobassessment.urls')),
]
JobAssessment App's URL.py:
from django.urls import path
from . import views
urlpatterns = [
path("", views.AssessmentListView.as_view(), name="assessment"),
]
This is my ListView that is called:
class AssessmentListView(LoginRequiredMixin, generic.ListView):
model = Assessment
template_name ='assessments_index.html'
paginate_by = 5
def get(self, request, *args, **kwargs):
# Ensure they have first created an Applicant Profile
if not Applicant.objects.filter(user=self.request.user).exists():
messages.info(request, "You must create a profile before you can view any assessments.")
return redirect('profile_create_form')
def get_queryset(self):
return Assessment.objects.all().filter(applicant=Applicant.objects.filter(user=self.request.user)).order_by('-assessment_stage')
If Applicant of current login user not exists then your if condition fails and since there is no else
part in there so there is no HttpResponse returned from the view. So please add else part if applicant exists and return HttpResponse()
class AssessmentListView(LoginRequiredMixin, generic.ListView):
model = Assessment
template_name ='assessments_index.html'
paginate_by = 5
def get(self, request, *args, **kwargs):
# Ensure they have first created an Applicant Profile
if not Applicant.objects.filter(user=self.request.user).exists():
messages.info(request, "You must create a profile before you can view any assessments.")
return redirect('profile_create_form')
else:
return HttpResponse() #<------ add corresponding HttpResponse if Applicant exists.
def get_queryset(self):
return Assessment.objects.all().filter(applicant=Applicant.objects.filter(user=self.request.user)).order_by('-assessment_stage')
Following the django document on ListView filter it's better to handle it within get_queryset. So for your case it would be something like this:
class AssessmentListView(LoginRequiredMixin, generic.ListView):
model = Assessment
template_name ='assessments_index.html'
paginate_by = 5
def get_queryset(self):
# Ensure they have first created an Applicant Profile
if not Applicant.objects.filter(user=self.request.user).exists():
messages.info(request, "You must create a profile before you can view any assessments.")
return redirect('profile_create_form')
else:
return Assessment.objects.all().filter(applicant=Applicant.objects.filter(user=self.request.user)).order_by('-assessment_stage')

Use existing sql-alchemy model class as flask-restplus api.model?

I am developing a CRUD application using vue.js and vuetify as frontend (view) and python flask-resplus and sqlAlchemy as backend (controler and model).
app/main/model/person.py
from sqlalchemy import Column, Integer, String, Date
from app.main.repository.base_repository import Base
class Person(Base):
__tablename__ = 'person'
id = Column(Integer, primary_key=True)
name = Column(String)
date_of_birth = Column(Date)
def __init__(self, name=None, date_of_birth=None):
if name is not None:
self.name = name
if date_of_birth is not None:
self.date_of_birth = date_of_birth
app/main/controller/person_controller.py
from flask_restplus import Namespace, fields, Resource, cors
from flask import request
from app.main.service.person_service import PersonService
from app.main.model.person import Person
api = Namespace('persons', description='Person related operations')
persServ : PersonService = PersonService()
model = api.model('Person', {
'id': fields.Integer,
'name': fields.String,
'date_of_birth': fields.Date
})
#api.route("/persons/all")
class PersonList(Resource):
#api.marshal_with(model)
def get(self, **kwargs):
return persServ.get_persons()
# return Person(name="Test", date_of_birth=date(1984, 10, 20))
#api.route("/person/<int:id>")
class PersonReturn(Resource):
#api.marshal_with(model)
def get(self, id):
return persServ.get_person(id)
#api.route("/person/<int:id>")
class PersonUpdate(Resource):
#api.marshal_with(model)
def put(self, id):
data = request.json
#TODO marshalling currently still error
return persServ.update_person(pers=data)
#api.route("/person")
class PersonCreate(Resource):
#api.marshal_with(model)
def post(self):
data = request.json
#TODO: check why person is not correctly linked to sql alchemy when reated here, make sure that model.Person is created
# pers = Person()
# pers.name = data['name']
# persServ.create_person(pers)
return persServ.create_person_02(data['name'])
#api.route("/person/<int:id>")
class PersonDelete(Resource):
def delete(self, id):
persServ.delete_person(id)
return '', 204
Questions also after implementing a spring java backend :
1) Is it necessary to provide an api.model in person_controller.py or can I annotate properties in person.py? Could you kindly guide me to a tutorial annotating an existing object?
2) Naming conventions flask api classes: In my eyes it definitely makes sense to use PersonList and Person instead of PersonUpdate, PersonCreate to ease API documentation as described in the flask-resPlus full example: https://flask-restplus.readthedocs.io/en/stable/example.html
However, I already have an existing Person class in person.py. I am thinking about having two person classes, a Person(Resource) in person_controller.py for Post, Put and Get operations and a Person in person.py as domain specific person object. However, I do not want to cause confusion and adhere to naming and orgainization good practices. What is the suggested naming approach? Is there a good example tutorial?

DRF Newbie - Stuck in small mistake kindly assist

I created 1 API its all working fine from all ends.
I created 2nd API the DRF headings title showing the headings of old api where i am doing mistake kindly assist.
serializers.py
from rest_framework import serializers
from .models import Brand, Category
class BrandSerializer(serializers.ModelSerializer):
class Meta:
model = Brand
fields = (
'id',
'name',
'slug',
'icon',
'featured_image',
'url'
)
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = (
'id',
'name',
'slug',
'featured_image',
)
products.url
router = routers.DefaultRouter()
router.register(r'', BrandViewSet)
router.register(r'', CategoryViewSet)
urlpatterns = [
path('', include(router.urls)),
]
product.view
class CategoryViewSet(viewsets.GenericViewSet, mixins.RetrieveModelMixin, mixins.ListModelMixin):
"""
API endpoint that allows sites to be viewed or edited
"""
queryset = Category.objects.all()
serializer_class = CategorySerializer
There is no error but in brower when i run the API url it shows brand list instead of category list,
The problem is that you have the views registered to the same endpoint. So it resolves the first one it finds.
So do the register to different endpoints like this:
router = routers.DefaultRouter()
router.register(r'brands', BrandViewSet)
router.register(r'categories', CategoryViewSet)
urlpatterns = [
path('', include(router.urls)),
]
So you can access brands via 127.0.0.1:8000/brands and categories via 127.0.0.1:8000/categories

Django View with two Slugs

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

Resources