Django search field in the database - python

is it possible to change my display employe to a search block because when I select the numbers it displays a list which is not practical when I have a lot of numbers in my database.
add info to an existing employee

You can define __str__() method for your Employee model, it result would be seen in admin dropdown
class Employee(models.Model):
first_name = models.CharField(max_length=50)
...
def __str__(self):
return self.first_name

Related

Django admin site: Unable to lookup 'child model' on 'parent model or 'parent modelAdmin'

This one's really difficult to write as a question since I'm not exactly sure how to ask this in the first place. But I'll try. Basically, I'm experiencing an AttributeError when I'm visiting the parent model in my django admin site. My current django database has 2 tables (except the prebuilt tables): a parent table / model for activity, and a child table / model for instruction. This is the structure of my models:
class activity(models.Model):
title = models.CharField(max_length=30,default=None)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User,on_delete=models.CASCADE,default=None)
def __str__(self):
return self.__class__.__name__
class instruction(models.Model):
detail = models.CharField(max_length=50,default=None)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User,on_delete=models.CASCADE,default=None)
activity = models.ForeignKey(activity,on_delete=models.CASCADE,default=None)
def __str__(self):
return self.__class__.__name__
So, if I add a new activity in the django admin site, say: Push-ups, then, I should be able to select this newly added parent record in the instruction form. However, when I try to add a new instruction record and select a saved activity record, the activity dropdown shows the name of the model only(in this case, activity). It doesn't show Push-ups. What I did next was to add some modelAdmins for the activity and instruction. Here's the code:
class activityAdmin(admin.ModelAdmin):
list_display = [field.name for field in activity._meta.get_fields()]
class instructionAdmin(admin.ModelAdmin):
list_display = [field.name for field in instruction._meta.get_fields()]
admin.site.register(activity, activityAdmin)
admin.site.register(instruction, instructionAdmin)
However, when I visit the activity page of the admin site this time, the page throws an AttributeError exception with the value Unable to lookup 'instruction' on activity or activityAdmin. This does not happen on the instruction page. I realized that this may not be the method to display the activity's title in the instruction form. Still, I need to add the modelAdmin in the admin.py in order to display all the fields of each models in the admin site. So in summary:
1. I need to display the parent model's field value (activity title) as an option in the child model's dropdown and not only the name of the parent model
2. I need to display the fields of each models on their respective registries in the admin site
Try updating your str definition. This is used as the dropdown display value and you are currently setting to the class name. If you want it to show the title in the dropdown:
class activity(models.Model):
title = models.CharField(max_length=30,default=None)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User,on_delete=models.CASCADE,default=None)
def __str__(self):
return self.title

Do i need to update AUTH_USER_MODEL in my settings.py?

I am creating my own users, Restaurant and Customer. I have extended the AbstractUser class and then created a OneToOneField field for each user. I am wondering if I need to add the AUTH_USER_MODEL in my settings.py. And also wondering what that does exactly...
What I was planning on doing was adding to my settings.py:
AUTH_USER_MODEL = 'myapp.Customer','myapp.Restaurant'
Do I have the right idea here?
My models.py:
class User(AbstractUser):
is_restaurant = models.BooleanField(default=False)
is_customer = models.BooleanField(default=False)
class Restaurant(models.Model):
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE)
restaurant_name = models.CharField(max_length=50)
def __str__(self):
return self.restaurant_name
class Customer(models.Model):
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE)
address = models.CharField(max_length=200)
def __str__(self):
return self.user.get_full_name()
No. AUTH_USER_MODEL isn't expecting a tuple, so this won't work.
In any case, Restaurant and Customer are not your user model; your subclassed User is. That's what you should be putting in that setting.
I would suggest create single user table instead of three different tables and add type as restaurant, customer, admin etc. And add only one table into settings file. this won't lead any further issues authentication etc. Having single user table is always robust. In your case having three tables seems not good to maintain.
========== UPDATE ===========
Create model for user named as CustomUser (or name which you feel better) and extends to User Model of Django using AbstractBaseUser,PermissionsMixin. like
class CustomUser(AbstractBaseUser): have all fields which user table has already. and add your desired table to bifurcate type of restaurant and
customer have type field with choices option.
For further help you can check section https://docs.djangoproject.com/en/1.11/topics/auth/customizing/#substituting-a-custom-user-model

Django ordering in admin [duplicate]

I'm trying to sort a Django Admin list page by a specific value in the objects' related foreign key set.
Specifically, in the below code, I want the ContentAdmin view to show a list of all content objects sorted by the "Twitter Score" (The Score object with name "Twitter").
In the django app I have the following models:
class Content(models.Model):
body = models.CharField(max_length=564)
title = models.CharField(max_length=64)
class Score(models.Model):
name = models.CharField(max_length=64)
score = models.IntegerField()
content = models.ForeignKey('Content')
And in the admin.py I have the following:
class ContentAdmin(admin.ModelAdmin):
list_display = ('title', 'show_twitter_score',)
def show_twitter_score(self, obj):
twitter_score = obj.score_set.get(name='Twitter')
return 'Twitter: ' + str(twitter_score.score)
GOAL: The admin panel for ContentAdmin displays the content objects ordered by "Twitter" scores
Thanks everyone!
I solved this by extending the get_queryset method of the ContentAdmin class. After that, it was just a matter of getting the right ORM query
def get_queryset(self, request):
qs = super(ContentAdmin, self).get_queryset(request)
return qs.filter(score__name='Twitter').order_by('-score__score')
For Django 1.5 and earlier, the method was queryset.
def queryset(self, request):
qs = super(ContentAdmin, self).queryset(request)
return qs.filter(score__name='Twitter').order_by('-score__score')
If I understand correctly, you can try this from ModelAdmin.list_display in Django's documentation:
Usually, elements of list_display that aren't actual database fields can't be used in sorting (because Django does all the sorting at the database level).
However, if an element of list_display represents a certain database field, you can indicate this fact by setting the admin_order_field attribute of the item.
For example:
class Person(models.Model):
first_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6)
def colored_first_name(self):
return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name)
colored_first_name.allow_tags = True
colored_first_name.admin_order_field = 'first_name'
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'colored_first_name')
The above will tell Django to order by the first_name field when trying to sort by colored_first_name in the admin.
You can try this workaround in your code for the sorting.
Since django admin uses the db to sort you cant sort on the function you are showing in the list.
What you can do is to add the column you want to show to the queryset that django admin is using to list your models, this way you can have sorting.
To add the column you need you have to use the queryset extra method.
This should do the trick :)
Content.objects.all().extra(select={'twitter_score': 'SELECT score from content_score WHERE content_score.id = content_content.id'})
BONUS ROUND:
Content.objects.all().extra(select={'twitter_score': 'SELECT 'Twitter score:' || score from content_score WHERE content_score.id = content_content.id'})

Using multiple columns as ForeignKey to return in another table

I'm new to Django so I make 3 simple tables to return a WishList. The thing is that I want whenever user asks for WishList, his/her user_id is used to make a SELECT query to return his/her own WishList. And I want to get product title and product url from my WishList table. I'm using to_field but with that way I only can get product title back. I don't know much about Django so help me!
Product
class Product(models.Model):
class Meta:
unique_together = (('id', 'title'),)
title = models.CharField(max_length=200, unique=True,
help_text='Name of the product')
url = models.CharField(max_length=300, default='',
help_text='Url of the product')
def __str__(self):
return 'Product: {}'.format(self.title)
WishList
class WishList(models.Model):
class Meta:
unique_together = (('user', 'product'),)
user = models.ForeignKey(fbuser,
on_delete=models.CASCADE,
help_text='Facebook user',
to_field='user_id')
product = models.ForeignKey(Product, to_field='title', db_column='title',
on_delete=models.CASCADE)
def __str__(self):
return 'WishList: {}'.format(self.user)
It's not a good practice to override to_field to another field different than your model.pk unless you have a really good reason and you know what you are doing (definitely not the case right now).
So after you read the docs, you will know that in order to get wishlisht related to a user, you can use the ForeignKey reverse relation to get all related wishlists for a user.
user_wishlists = my_user.wishlist_set.all()
#Because we know that you want to access the wishlist.products
#in order to optimize things (in terms of db queries)
#you can add and .select_related('product')
#e.g, user_wishlists = my_user.wishlist_set.all().select_related('product')
#now follow the wishlist.product foreign key to access the related product for every wishlist
for wishlist in user_wishlists:
product = wishlist.product
print (product.id, product.title, product.url)
Now after you read a little bit more of the documentation
you will notice that your WishList model is in fact an intermediate model for a ManyToMany relation between User and his wished products, then you will know that you can define a M2M field between user and products via WishList like so:
class FbUser(models.Model):
#...
wished_products = models.ManyToManyField(
Product,
through='WishList',
through_fields=('user', 'product')
)
#and now accessing user wished products would be easy as:
user_wished_products = my_user.wished_products.all()
for product in user_wished_products:
print (product.id, product.title, product.url)

Django admin, show 2 or more attributes in a field

I got a model where a "student" is able to enrol to a "course". The issue is that courses may have the same name(but different attendance, 'full time' or 'part time'). So as you can see in the image attached, I would like to know which course a student is enrolled to. Either inside the select box or next to it. I tried to use a list display but couldn't figure out how to use it.
Edit: the field that the type of attendance is stored is called 'attendance' and it's part of the class 'Course'.
admin.py
class StudentAdmin(admin.StackedInline):
model = Student
verbose_name_plural = 'students'
# Define a new User admin
class UserAdmin(UserAdmin):
inlines = (StudentAdmin, )
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
On the Course model you can define the __unicode__(self): method to interpolate two attributes together. So, in your case you could combine the name of the course and the attendance.
That would look something like this:
class Course(models.Model):
name = models.CharField(max_length=100)
attendance = models.CharField(max_length=100)
def __unicode__(self):
return "%s (%s)" % (self.name, self.attendance)
Then the string representation of that course will be the name of the course followed by the attendance in parenthesis.
An example of this can be found in the documentation.

Categories

Resources