Pull object from database in views.py - python

I would like to create a function in views.py to retrieve an information from this class:
class Vin(models.Model):
def __unicode__ (self):
return self.nom
name = models.CharField( max_length = 30)
year = models.CharField (max_length = 4)
appellation = models.ForeignKey(Appellation)
photo = models.CharField (max_length = 70)
quantity = models.IntegerField ()
released = models.IntegerField()
and retrieve it by its attribute "name".
So for instance, if i have a Wine ("chardonnay", 1990, ...) only retrieve chardonnay.
Thanks !

Your view function will be called after the user enters a URL that is in your urls.py. The url entered may provide you with the additional information you need to query the database and get information on the Vin object you need.
If you want a view to just return every Vin in your database. Something like this might be helpful for you:
def get_vins(request, *args, **kwargs):
vins = Vin.objects.all().values_list('name', flat=True)
return render(request, 'somepage.html', {"vins": vins})
Your question is really vauge and you should read the django documentation. This is a very basic question that all starters should learn.

Related

Django: How to write a function based view used for URL with parameter

I am learning Django, using function based views, and I am struggling with the following:
I have this path in urls.py
path('user/<str:username>',views.UserProjectList,name='user-projects')
that is supposed to show all the projects of the particular user (client). In order to reach it, username should be parameter of the function based view, however I am struggling how to write such view...
I have this:
def UserProjectList(request,username):
user = User.objects.get(username=username) #THIS IS WRONG and should return id of the user
#user = User.objects.filter(username=username) #also wrong
tag_list = ProjectTagsSQL.objects.all() #ProjectTagsSQL and ProjectSQL are connected
project_list = ProjectSQL.objects.filter(client=user) #ProjectSQL table has column client_id (pk is id in User) and table contains all the projects
context = {
'tagy' : tag_list,
'projecty' : project_list
}
return render(request, 'home_page/user_projects.html', context) #SHOULD THE PARAMETER BE INCLUDED HERE?
I tried to inspire with the code from class based view I found on the internets (thats is working for me but i didnt manage to connect it with ProjectTagsSQL as i managed in FBV, but that's a different problem) but i didnt manage
class UserProjectListView(ListView):
model = ProjectSQL
template_name = 'home_page/user_projects.html'
context_object_name = 'data'
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return ProjectSQL.objects.filter(client=user)
Could someone help me how to deal with such function based view please? As this solution its not working (will return nothing for any user)
Here is also the ProjectSQL model (and ProjectTagsSQL model) :
class ProjectSQL(models.Model):
id = models.AutoField(primary_key=True)
country = models.TextField()
city = models.TextField()
time_added = models.DateTimeField(default=timezone.now)
start_date = models.DateField()
end_date = models.DateField()
client = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
managed = False #https://docs.djangoproject.com/en/4.0/ref/models/options/
db_table = 'project'
class ProjectTagsSQL(models.Model):
id = models.IntegerField(primary_key=True)
project = models.ForeignKey(ProjectSQL, on_delete=models.CASCADE)
tag = models.ForeignKey(ProjectTagSQL, on_delete=models.CASCADE)
class Meta:
managed = False # https://docs.djangoproject.com/en/4.0/ref/models/options/
db_table = 'project_tags'
You need to write user.id so:
from django.shortcuts import get_object_or_404
def UserProjectList(request,username):
user = get_object_or_404(User,username=username)
tag_list = ProjectTagsSQL.objects.all()
project_list = ProjectSQL.objects.filter(client=user.id)
context = {
'tagy' : tag_list,
'projecty' : project_list
}
return render(request, 'home_page/user_projects.html', context)
Also, try to check template variables' name, whether you used same or not.
Note: Always append / at the end of every route so it should be path('user/<str:username>/'....
Note: Function based views are generally written in snake_case so it is better to name it as user_project_list instead of UserProjectList.

Loading extra fields for update in Django dependent dropdown list

I implemented a dependent dropdown on my Django webapp. I used this tutorial Implementing dependent drop down. However, challenge comes when I want to update the form. To put this in perspective, let me recreate the code here.
Model.py
class VehicleMake(models.Model):
make = models.CharField(max_length=20)
manufacturer = models.CharField(max_length=20)
def __str__(self):
return self.make
class VehicleModel(models.Model):
make = models.ForeignKey(VehicleMake, on_delete=models.CASCADE)
model_name = models.CharField(max_length=20)
def __str__(self):
return self.model_name
class Vehicle(models.Model):
model = models.ForeignKey(VehicleModel, on_delete=models.CASCADE)
description = models.TextField()
Notice that unlike in the provided tutorial, I don't have both of the dependent fields on the vehicle model. That is to avoid repetition since if you know the vehicle model, you will definitely know the make from the VehicleModel table.
Here is the form:
forms.py
class VehicleDetails(forms.ModelForm):
make = forms.ModelChoiceField(queryset=VehicleMake.objects.all(),
empty_label="Select Vehicle Make")
class Meta:
model = Vehicle
fields = ['make', 'model', 'description'
]
def __init__(self, *args, **kwargs):
super(VehicleDetails, self).__init__(*args, **kwargs)
self.fields['model'].queryset = VehicleModel.objects.none()
if 'make' in self.data:
try:
make = int(self.data.get('make'))
self.fields['model'].queryset = VehicleModel.objects.filter(make=make).order_by('model_name')
except (ValueError, TypeError):
pass # invalid input from the client; ignore and fallback to empty VehicleModel queryset
elif self.instance.pk:
vehicle_model = VehicleModel.objects.get(self.instance.model)
self.fields['make'] = vehicle_model.make
self.fields['model'].queryset = self.instance.model_set.filter(make=vehicle_model.make).order_by('model_name')
So, my challenge is, when I want to update the form, I get an error from the last section of the form under the elif code. I want to get the value of make using the store value of model then use that to render the form of course with the select of options of model being those from the selected make, unless the user now makes changes to the make field.
This is what I have tried so far (especially under the elif section on the forms.py) but I keep getting the error: TypeError: 'VehicleModel' object is not iterable. What am I doing wrong?
I was able to solve this by changing this in the elif block:
vehicle_model = VehicleModel.objects.get(pk=self.instance.model.id)
self.fields['make'].queryset = self.instance.model.make.__class__.objects.all()
self.fields['model'].queryset = self.instance.model.__class__.objects.filter(make=vehicle_model.make).order_by('model_name')
Then all I had to do at the views.py to ensure that current value is loaded was to add a initial value while loading the form, i.e.
vehicle_form = VehicleDetails(instance=listing.vehicle, initial = {'make': listing.vehicle.model.make })
I hope it helps anyone in the same problem.

DRF changing field name values of django models with foreign keys

I followed suggestion from this question
But i need to name one field of query_set to date filed of another object
My models are
class Choice(models.Model):
question = models.ForeignKey(Question, related_name='choice', on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
class ChoiceWithTime(models.Model):
choiceTime = models.ForeignKey(Choice,related_name='choiceTime', on_delete=models.CASCADE)
choice_date=models.DateField()
My view
class QuestionChoicesViewSet(viewsets.ModelViewSet):
queryset = Choice.objects.all()
serializer_class = ChoiceDateSerializer
def get_queryset(self):
return Choice.objects.values('choiceTime__choice_date','choice_text').annotate(
total_votes=Count('choiceTime__choice_date'),
)
I need to count number of submission in particular dates
I don't know how to name choiceTime__choice_date that serializer recognizes field in query set
class ChoiceDateSerializer(serializers.ModelSerializer):
choiceTime__choice_date = serializers.DateTimeField()
total_votes = serializers.IntegerField()
class Meta:
model = Choice
fields = ('id', 'choice_text','total_votes','choiceTime__choice_date')
i receive
{
"choice_text": "ant tower",
"total_votes": 3,
"choiceTime__choice_date": "2017-04-20"
}
But i want to recieve
{
"choice_text": "ant tower",
"total_votes": 3,
"choice_date": "2017-04-20"
}
Tried different options with no success. Definitely i am missing the point.
For my purposes it is working, but i want to have well written API.
2 option change time submission model?
class ChoiceWithTime(models.Model):
choiceTime = models.ForeignKey(Choice,related_name='choiceTime', on_delete=models.CASCADE)
choice_date=models.DateField()
coutner = models.IntegerField(default=0)
Is 2 option considers to be better approach to my particular problem? Thanks!
You are receiving a json object, which you add its key value.
for vote_detail in data:
if vote_detail.choiceTime__choice_date:
vote_detail.choice_date=vote_detail.choiceTime__choice_date
then serialize and save, a quick solution.
You could also add to your model the name that you want to call it. That's closer to backend and maybe worth delving into.
from django.db.models import Count,F
If anybody finds this problem and this is easiest answer i came up to.
As it was suggested before passing to serializer change value using model package functions
class QuestionChoicesViewSet(viewsets.ModelViewSet):
queryset = Choice.objects.all()
serializer_class = ChoiceDateSerializer
def get_queryset(self):
return Choice.objects.all().annotate(choice_date=F('choiceTime__choice_date')).values('choice_date','choice_text').annotate(
total_votes=Count('choiceTime__choice_date'),
)

Django Model Not Updating

I'm trying to count the amount of times a user visits a page:
models.py:
class Request(models.Model):
user = models.ForeignKey(User)
view = models.CharField(max_length = 250)
visits = models.PositiveIntegerField()
views.py
def daygaps(request,*a, **kw):
request_counter = Request.objects.filter(
user__username = request.user.username, view = 'daygaps')
if request_counter:
request_counter[0].visits += 1
request_counter.update()
else:
Request.objects.create(
user = request.user,
visits = 1,
view = 'daygaps')
When a new user visits the page for the first time, 'visits' gets set to = 1. Each subsequent visit should iterate the count. The "else" block works fine, however "visits" stays at 1 and does not change with each new request a user makes.
I've tried the ".save()" method, but that throws an error because "request_counter" is a queryset.
You could do something like this:
models.py
class Request(models.Model):
user = models.ForeignKey(User)
view = models.CharField(max_length = 250)
visits = models.PositiveIntegerField(default=0)
views.py
def daygaps(request,*a, **kw):
request_counter = Request.objects.get_or_create(
user = request.user, view = 'daygaps')
request_counter.visits += 1 # or =F('visits')+1 to avoid a race condition as suggested by Moses Koledoye
request_counter.save()
OR
models.py
class Request(models.Model):
user = models.ForeignKey(User)
view = models.CharField(max_length = 250)
visits = models.PositiveIntegerField(default=1)
views.py
def daygaps(request,*a, **kw):
updated_count = Request.objects\
.filter(user = request.user, view = 'daygaps')\
.update(visits=F('visits')+1)
if not updated_count:
Request.objects.create(user = request.user, view = 'daygaps')
which avoids race conditions too and has an added advantage of not having to retrieve the object.
In general, I guess the second one is better if the update is simple enough to be implemented with F expressions.
Instead of using filter and indexing the list returned by the QuerySet, you could simply use .get to return the object:
from django.db.models import F
def daygaps(request,*a, **kw):
...
request_counter = Request.objects.get(
user__username = request.user.username, view = 'daygaps')
request_counter.visits = F('visits') + 1
request_counter.save()
You can wrap the logic in a try/except to handle DoesNotExist exceptions.
The F expression helps you manage race conditions. Read more: Updating attributes based on existing fields

Django foreign key access in save() function

Here's my code:
class Publisher(models.Model):
name = models.CharField(
max_length = 200,
unique = True,
)
url = models.URLField()
def __unicode__(self):
return self.name
def save(self):
pass
class Item(models.Model):
publisher = models.ForeignKey(Publisher)
name = models.CharField(
max_length = 200,
)
code = models.CharField(
max_length = 10,
)
def __unicode__(self):
return self.name
I want to be able to access each Item from the Publisher save function. How can I do this?
For instance, I'd like to append text to the code field of each Item associated with this Publisher on the save of Publisher.
edit:
When I try to implement the first solution, I get the error "'Publisher' object has no attribute 'item_set'". Apparently I can't access it that way. Any other clues?
edit 2:
I discovered that the problem occurring is that when I create a new Publisher object, I add Items inline. Therefor, when trying to save a Publisher and access the Items, they don't exist.
Is there any way around this?!
You should be able to do something like the following:
def save(self, **kwargs):
super(Publisher, self).save(**kwargs)
for item in self.item_set.all():
item.code = "%s - whatever" % item.code
I don't really like what you're doing here, this isn't a good way to relate Item to Publisher. What is it you're after in the end?

Categories

Resources