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
Related
I have a database table called Supplier that has a foreign key of User, each User has their own Suppliers. I got the get request working so that it returns all Suppliers in the entire table, but I can not find a way to filter it so I only receive the Suppliers associated with the User requested.
I am accessing this request by this URL:
http://localhost:8000/pm/getsuppliers/primary-key-of-user/
models.py:
class UserProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
bio = models.CharField(max_length=200)
email = models.CharField(max_length=200)
class Supplier(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
phone = models.IntegerField()
email = models.EmailField(max_length=200)
views.py:
class getsuppliers(viewsets.ModelViewSet):
queryset = Supplier.objects.all()
serializer_class = GetSuppliersSerializer
lookup_field = 'user'
serializers.py:
class GetSuppliersSerializer(serializers.ModelSerializer):
class Meta:
model=Supplier
fields=['pk','user','name','email','phone']
The error I am receiving:
ERROR: pm.models.Supplier.MultipleObjectsReturned: get() returned more than one Supplier -- it returned 10!
I have done some searching on this error and they are saying to use .filter instead of .all in the view, but I am not sure how to make it return ALL Suppliers for the requested User, this seems like it would only return 1. Maybe I am wrong, hopefully someone has an easy solution!
You'll have to set the serializer's model (inside Meta) to User, and add in a supplier_set field:
class GetUserSuppliersSerializer(serializers.ModelSerializer):
supplier_set = SupplierSerializer(read_only=True, many=True)
class Meta:
model = User
fields = ['supplier_set']
class SuppliersSerializer(serializers.ModelSerializer):
class Meta:
model = Supplier
fields = ['pk','user','name','email','phone']
And also change the viewset queryset to get users.
Edit:
To answer the question in the comment, there are a few different ways to do that based on what you need, one way is to add a to_representation method in your GetUserSuppliersSerializer as such:
def to_representation(self, instance):
response = super().to_representation(instance)
response["supplier_set"] = sorted(response["supplier_set"], key=lambda x: x["pk"])
return response
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'
)
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.
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.
I'm still a novice so any help is gladly appreciated. Running Django 1.10
I'm trying to retrieve all the profiles that are assigned a particular manager but my query set always comes up empty.
Model.py
Blockquote
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=30, blank=False)
last_name = models.CharField(max_length=30, blank=False)
email = models.EmailField( blank=True, help_text='Optional',)
receive_email_notifications = models.BooleanField(default=False)
manager = models.ForeignKey(User, unique=False, blank=True, related_name='+', null=True)
def get_full_name(self):
"""
Returns the first_name plus the last_name, with a space in between.
"""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def publish(self):
return self.save
def __str__(self):
return str(self.user)
View.py
Blockquote
def instrument_list(request):
# pulls all instruments from instrument model
instruments = Instrument.objects.all().order_by('instrument_name')
test = Profile.objects.filter(manager='jenn')
print(test)
# pulls all checklists from checklist model
checklists = Checklist.objects.all().order_by('created_date')
# takes instruments, pushes them to template with variable 'instruments'
return render(request, 'blog/instrument_list.html', {'instruments': instruments, 'checklists': checklists})
I've also tried filtering a single profile entry (with a non-foreign key attribute) and printing how managers are saved in the database and the output looked like this
Blockquote
<User: jenn>
However, even when I try filtering with that output, my query sets come up empty
Blockquote
test = Profile.objects.filter(manager='<User: jenn>')
I think I need to adjust my filter parameter to something the database can match against but I'm not sure what that format is. I've tried looking through the documentation but haven't found exactly what I'm looking for.
But that's just a string representation of a model instance. You need the actual instance.
jenn = User.objects.get(username="Jenn")
test = Profile.objects.filter(manager=jenn)
Of course, once you already have jenn as an instance, to can use the reverse accessor of the fk instead:
test = jenn.profile_set.all()
And if you don't have jenn, and you don't need it, you can do the whole thing in one query:
test = Profile.objects.filter(manager__username="Jenn")
I've also tried filtering a single profile entry (with a non-foreign key attribute) and printing how managers are saved in the database and the output looked like this
That's not how managers are saved in databases, thats just a "readable" representation of an instance user.
If you want to filter on a manager you can do something like that :
test = Profile.objects.filter(manager__pk= primary_key_of_manager)
or
temp_manager = User.objects.get(...)
test = Profile.objects.filter(manager=temp_manager)