How to add variable in Django model - python

I want to add variable in Django model and I don't want to save it to database at the same time I want to return this variable to user when calling the endpoint.
this is what i found in the web, but the problem is the variable is not rerun to user
class User (models.Model):
f_name = models.CharField(max_length=255)
l_name = models.CharField(max_length=300)
full_name = ''
How to rerun the full_name to user when he call the api ?

If this is using Django Rest Framework, I don't know how your code is set up, but you'll need to extend your serializer:
add a new field to the serializer: full_name = serializers.SerializerMethodField()
add a method to the serializer:
def get_full_name(self, obj):
return "{} {}".format(obj.first_name, obj.last_name)
NOTE:
there are LOTS of different ways of joining those strings together, using #property in your model, fstrings, etc - up to you to choose the most appropriate for your needs (without seeing the rest of your code()

You can define model's property:
class User (models.Model):
f_name = models.CharField(max_length=255)
l_name = models.CharField(max_length=300)
#property
def full_name(self):
return self.f_name + self.l_name
now you use full_name same way as normal attribute user.full_name.

Related

Django: Block access to not authorized users in CreateView

I have a problem for block access to not authorized user in pages dedicated to add new objects. List of that users is stored in many-to-many field in project object and in foreign key field.
Below is models.py
class Project(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name="projects_as_owner", null=True)
project_managers = models.ManyToManyField(User, related_name="projects_as_pm", blank=True)
name = models.CharField(max_length=200)
description = models.TextField(blank=True)
date_of_insert = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Milestone(models.Model):
project_fk = models.ForeignKey(Project, related_name="milestones", on_delete=models.CASCADE)
name = models.CharField(max_length=200)
description = models.TextField(blank=True)
date_of_insert = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
And views.py with class I have problem
class NewMilestone(LoginRequiredMixin, generic.CreateView):
model = Milestone
fields = ['name', 'description']
lookup_url_kwarg = 'p_id'
template_name = 'main/new_milestone.html'
# ... two functions, that work good, not important here ...
def get_queryset(self):
qs = super(NewMilestone, self).get_queryset()
project = Project.objects.get(id=self.kwargs['p_id'])
if(qs.filter(project_fk__owner=self.request.user).exists() or User.objects.filter(id=self.request.user.id).filter(projects_as_pm__id=project.id).exists()):
return qs
else:
return Http404("You are not authenticated to this action")
Objective here is here to allow authenticated users (owner and project manager/s) to enter this view and for anybody else show info about declined access.
Problem is that, that method, get_queryset, doesn't block unauthorised users in CreateViev class.
I tried some configurations for that issue, every single one I used had this flaw.
My question here is how to make it work the way I expect from it?
PS. English is not my native language and it was a while since I wrote something, so please be understanding.
You are using the LoginRequiredMixin which is a good thing. But then you didn't set any of the parameters available.
LoginRequiredMixin inherits from AccessMixin and you can use all it's parameters with which it shouldn't be too complicated to cover your case.
Here's a possible implementation:
class NewMilestone(LoginRequiredMixin, generic.CreateView):
...
# your class attributes
...
raise_exception = True
# Returns a permission denied message. Default: empty string
def get_permission_denied_message(self):
return "Access is restricted to authenticated users"
If you have raise_exception set to True then the get_permission_denied_message method will be called. Otherwise the user will be redirected to the login_url which you also would have to declare as a class attribute.

DJANGO get objects in sql like join

Context: I'm forcing my self to learn django, I already wrote a small php based website, so I'm basically porting over the pages and functions to learn how django works.
I have 2 models
from django.db import models
class Site(models.Model):
name = models.CharField(max_length=50, unique=True)
def __str__(self):
return self.name
class Combo(models.Model):
username = models.CharField(max_length=50)
password = models.CharField(max_length=50)
dead = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True)
siteID = models.ForeignKey(Site, on_delete=models.PROTECT)
class Meta:
unique_together = ('username','siteID')
def __str__(self):
return f"{self.username}:{self.password}#{self.siteID.name}"
When creating a view, I want to get the Combo objects, but I want to sort them first by site name, then username.
I tried to create the view, but get errors about what fields I can order by Cannot resolve keyword 'Site' into field. Choices are: dead, id, password, siteID, siteID_id, timestamp, username
def current(request):
current = Combo.objects.filter(dead=False).order_by('Site__name','username')
return render(request, 'passwords/current.html',{'current':current})
Since I'm not necissarily entering the sites into the database in alphabetical order, ordering by siteID wouldn't be useful. Looking for some help to figure out how to return back the list of Combo objects ordered by the Site name object then the username.
You can order this by siteID__name:
def current(request):
current = Combo.objects.filter(dead=False).order_by('siteID__name','username')
return render(request, 'passwords/current.html',{'current':current})
since that is the name of the ForeignKey. But that being said, normally ForeignKeys are not given names that end with an ID, since Django already adds an _id suffix at the end for the database field.
Normally one uses:
class Combo(models.Model):
# …
site = models.ForeignKey(Site, on_delete=models.PROTECT)
if you want to give the database column a different name, you can specify that with the db_column=… parameter [Django-doc]:
class Combo(models.Model):
# …
site = models.ForeignKey(
Site,
on_delete=models.PROTECT,
db_column='siteID'
)

How to change field in ModelForm generated html form?

I'm making one of my first django apps with sqlite database. I have some models like for example:
class Connection(models.Model):
routeID = models.ForeignKey(Route, on_delete=models.CASCADE)
activityStatus = models.BooleanField()
car = models.ForeignKey(Car, on_delete=models.CASCADE)
class Route(models.Model):
name = models.CharField(max_length=20)
and forms
class RouteForm(ModelForm):
class Meta:
model = Route
fields = ['name']
class ConnectionForm(ModelForm):
class Meta:
model = Connection
fields = ['routeID', 'activityStatus', 'car']
And in my website, in the url for adding new Connection, I have cascade list containing RouteIDs. And I'd like it to contain RouteName, not ID, so it would be easier to choose. How should I change my ConnectionForm, so I could still use foreign key to Route table, but see RouteName instead of RouteID?
For now it's looking like this, but I'd love to have list of RouteNames, while still adding to Connection table good foreign key, RouteID
Update the Route Model's __str__ method:
class Route(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
Because the __str__() method is called whenever you call str() on an object. Django uses str(obj) in a number of places like in Modelform. By default it returns id or pk that is why you were seeing ids in model form. So by overriding it with name, you will see the names appear in choice field. Please see the documentation for more details on this.

Searching a Class by User ForeignKey

I have searched high and low and even in between and for some reason cannot come up with a clear answer...
I am using django1.9 and created this model:
class paymentInfo(models.Model):
"""
Model for storing payment info
- Username as ForeignKey from userToCard
- Store payment token
- Store last 4
- Store card/bank name
- Store bool value for Default method
"""
username = models.ForeignKey(User, db_column='username', on_delete=models.CASCADE)
token = models.CharField(max_length=10)
last_4 = models.IntegerField()
bank_name = models.CharField(max_length=50)
default = models.BooleanField(default=0)
class Meta: # meta class to define the table name
db_table = 'payment_methods'
verbose_name_plural = 'Payment Methods' # for the admin site display
ordering = ('username',)
def __str__(self):
# in __str__ you should return a value of type string
# so self.username changed to self.username.username
return self.username.username # value displayed in admin view
I have created some objects using some different usernames and want to filter out the paymentInfo objects by user.
When I store the object, the database stores the user pk under the username column instead of the actual username string. I am not sure why, but that is not my issue here.
My issue is when I am trying to filter out paymentInfo.objects using the username or the user pk. I cannot seem to filter it out and the error I normally get is thus: FieldError: Cannot resolve keyword 'username' into field. Choices are: bank_name, default, id, last_4, token
P.S. I am using MySQL
If I understood you right, you are trying to filter data by username from table User what is a foreign key. In this case, this should help
paymentInfo.objects.filter(username__name='John')
Thanks to the answers provided, I was able to work out a solution (mainly using #Aamir Adnan 's method.)
class paymentInfo(models.Model):
"""
Model for storing payment info
- Username as ForeignKey from userToCard
- Store payment token
- Store last 4
- Store card/bank name
- Store bool value for Default method
"""
user = models.ForeignKey(User, on_delete=models.CASCADE)
token = models.CharField(max_length=10)
last_4 = models.IntegerField()
bank_name = models.CharField(max_length=50)
default = models.BooleanField(default=0)
class Meta: # meta class to define the table name
db_table = 'payment_methods'
verbose_name_plural = 'Payment Methods' # for the admin site display
ordering = ('user',)
def __str__(self):
return self.user # value displayed in admin view
def __unicode__(self):
return '%s' % (self.user)
The new __unicode__ inside of my class was so that I did not receive this error anymore:
TypeError: coercing to Unicode: need string or buffer, User found

Create editable Template with multiple models in one form

i read a lot of forms.
i want to edit userinformation, but the userinformation is existed of two models.
One model this:
class Tc(LoginUser):
link = models.CharField(max_length=100)
name = models.CharField(max_length=50, unique=True)
contact = models.OneToOneField(Contact, blank=True, null=True)
def __str__(self):
return self.name
And the second one:
class Contact(models.Model):
contact_id = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
def __str__(self):
return self.email
Now i want to edit "contact" field.
It should be controled, if a contact is existing, if not, so create a new. If there is an existing one, then update this.
My problem is that, that i must use two forms and i dont know how exactly.
You need to make queries : for handle contact and know about a contact existing you need Making queries
. as a hint for check about existing if you have one unique object of contact like check_name you can do it with following :
from models import Contact
contats=contact.objects.all()
for n in contacts:
if n.first_name == check_name()
#do something
else:
#do something

Categories