I have 2 django models like this:
class UserProfile(models.Model):
user = models.OneToOneField(User)
organisation = models.CharField(max_length=200)
class Submission(models.Model):
user = models.ForeignKey(User)
date_submission = models.DateTimeField(db_index=True, default=datetime.now())
date_published = models.DateTimeField(db_index=True, null=True)
status = models.CharField(db_index=True, max_length=4000)
logfile = models.TextField(db_index=False)
where each 'Submission' object is owned by a normal django user, and each user has a UserProfile configured using the AUTH_PROFILE_MODULE in the normal way.
This works as you would expect, i can see the organisation field of the UserProfile object:
Submission.objects.all()[0].user.userprofile.organisation
When i want to serialize the Submissions list (for export to json) normally i use:
Submission.objects.all().values()
# or for more control of fields
Submission.objects.all().values('status', 'date_submission')
# to traverse a relationship.. get info from the User object
Submission.objects.all().values('user__username')
.. these work fine. BUT my problem is that i cannot:
Submission.objects.all().values('user__userprofile__organisation')
raise FieldError("Invalid field name: '%s'" % name)
django.core.exceptions.FieldError: Invalid field name: 'user__userprofile__organisation'
so it seems that the UserProfile is a 'special case'. This was discussed here:
Django query : Call values() on user__userprofile
but the solution doesn't help me (i'm fairly sure..)
Is this a limitation of the values() method ? does anyone know a way to get the same output of values() but able to traverse the UserProfile model ?
thanks for any ideas
-i
Turns out upgrading to version 1.4 of Django solved the problem, the comment by Jingo suggests 1.3.1 would also be ok.
so now i can:
query_set = Submission.objects.filter()
query_set.values('user__userprofile__organisation')
[{'user__userprofile__organisation': u'organisation test 1'}]
cheers
-i
Related
I have two models: Post and User (the standard Django User model - thus not shown below)
class Post(models.Model):
# post_file = CloudinaryField(resource_type='video',blank=True)
post_file = models.CharField(max_length=500,blank=False,default="")
user = models.ForeignKey(User, on_delete=models.CASCADE)
description = models.CharField(max_length=150,blank=False,default="")
approved = models.BooleanField(default=False)
active = models.BooleanField(default=False)
I want to filter Posts where either the post description or the User.user_name contains a search string.
e.g. search_crit ='erch'
Tried many approaches but the solution keeps evading me.
from django.db.models import Q
active_post_views = Post.objects.filter(active=True, approved=True).select_related('user')
matched_active_post_views = active_post_views.filter(
Q(description__contains=search_crit) |
Q(username__contains=search_crit)
)
The above fails, so obviously not correct. It has a problem with the Q(username__contains=search_crit) portion of the filter. I have also tried Q(user_username__contains=search_crit), to no avail.
Any advice would be much appreciated.
The username is in the user field, so you filter with user__username__contains=…. You thus look "through" relations with two consecutive underscores (__):
matched_active_post_views = active_post_views.filter(
Q(description__contains=search_crit) |
Q(user__username__contains=search_crit)
)
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
How do I use select_related to get the first and last name of the employee class below.
class Employee(models.Model):
"""
Model, which holds general information of an employee.
"""
user = models.OneToOneField(User, related_name='users',
on_delete=models.CASCADE, unique=True)
photo_logo = models.FileField(null=True, blank=True)
Here is how I have implemented my query
emp=Employee.objects.filter(pk=1).select_related('user').values('user_first_name','user_last_name','id')
But I get the following logs after running a print statement in django shell
Cannot resolve keyword 'user_first_name' into field. Choices are: address, address_id, attendance, basic,
Since you need specific fields of user model, you dont need select_related in this case, just use:
emp=Employee.objects.filter(pk=1).values('user__first_name','user__last_name','id')
query.
Note that you shoulduse double underscore __ to perform join.
We should use __ for relation field
emp=Employee.objects.filter(pk=1).select_related(
'user'
).values('user__first_name','user__last_name','id')
Is there a Djangotastic way to display a default value for a field in the admin when there isn't a value? Like 'n/a', but not to save that to the database?
When I set all the fields in the model below to readonly in the admin, the front-end display looks like the image at the bottom. It feels visually collapsed like it should have a value or a box or something. If there isn't an easy way to do what I am looking for, then is there another solution to make the front-end admin more clear for the user?
class Package(models.Model):
packaging_format = models.CharField(max_length=40)
package_delivery_pattern = models.CharField(max_length=30, blank=True)
package_delivery_comments = models.CharField(max_length=250, blank=True)
package_manifest_filename = models.CharField(max_length=50)
package_description = models.CharField(max_length=250, blank=True)
package_naming_pattern = models.CharField(max_length=50)
Screenshot of fields as displayed in the admin:
What's happening is that your actually saving a empty string '' in your CharFields instead of None values (because of the blank=True). So the Django-admin is showing the string you saved in the db (in this case, nothing).
If you change your CharFields to null=True instead of blank=True, you will be saving NULL in your database instead of an empty string. And that way, you will get the behaviour you want.
EDIT: I know this solution is not recommended (following Django Docs), but that's the behaviour you wanted. Django-admin is just showing you the string you have in the database, which is ''.
Another solution that comes to my mind is to modify the ModelAdmin for your Package model, something like:
class PackageAdmin(admin.ModelAdmin):
readonly_fields = ['show_package_delivery_pattern', ...]
def show_package_delivery_pattern(self, obj):
if obj.package_delivery_pattern:
return obj.package_delivery_pattern
else:
return 'N/A'
# same with all your CharFields..
As of Django 1.9 you can use empty_value_display at the site, model, or field level in the Django admin. At the model level:
class YourModelAdmin(admin.ModelAdmin):
empty_value_display = '---'
I'm developing a small Django site and I'm using django.contrib.admin to handle content management. I'd like to capture the first name & last name of the author (an Admin user) of an Article on its initial save (and not update it if another user edits the Article).
ie.
class Article(models.Model)
title = models.CharField(max_length=50)
pub_date = models.DateTimeField('date published')
author = ForeignKey(???)
...
What do I need to write to grab this user's first name & last name fields when creating a new Article object? I'd default to their admin username if those fields are blank.
Have your model use the User object:
author = models.ForeignKey(User)
To prevent this field from being changeable on update, check out this other SO post:
Django admin: exclude field on change form only
To change the admin's Select field to use first/last name, you could try this snippet:
http://djangosnippets.org/snippets/1642/
To change the admin's view, assuming you are using the built-in templates, you could add a custom column as described on this post: How do I add a custom column with a hyperlink in the django admin interface?
class AuthorAdmin(admin.ModelAdmin):
list_display = ('author_name',)
def my_author_name(self, obj):
if obj.author.first_name and obj.author.last_name:
return '%s %s' % (obj.author.first_name, obj.author.last_name)
else:
return obj.author.username
my_author_name.allow_tags = True
my_author_name.short_description = 'Author'
I think you are looking for this:
author = models.ForeignKey(User)
It looks like the best way to handle a None or blank result from get_full_name is to just populate User.author with models.ForeignKey(User) and then — at the template level — use the following:
{{ user.get_full_name|default:user.username }}
... via this SO answer. This allows me to perform queries on a User's Articles, but still gracefully handles blank first_name & last_name fields if a User hasn't entered them yet, but will also update dynamically when they have).
I have a User model and a Submission model. Each Submission has a ForeignKey field called user_submitted for the User who uploaded it.
class Submission(models.Model):
uploaded_by = models.ForeignKey('User')
class User(models.Model):
name = models.CharField(max_length=250 )
My question is pretty simple: how can I get a list of the three users with the most Submissions?
I tried creating a num_submissions method on the User model:
def num_submissions(self):
num_submissions = Submission.objects.filter(uploaded_by=self).count()
return num_submissions
and then doing:
top_users = User.objects.filter(problem_user=False).order_by('num_submissions')[:3]
But this fails, as do all the other things I've tried. Can I actually do it using a smart database query? Or should I just do something more hacky in the views file?
from django.db.models import Count
top_users = User.objects.filter(problem_user=False) \
.annotate(num_submissions=Count('submission')) \
.order_by('-num_submissions')[:3]
You didn't mention problem_user in your example model code, but I've left it in assuming that it is a BooleanField on User.