how to display many error django - python

i have following models
class tags(models.Model):
tag = models.CharField(max_length=15) # Tag name
tagDescription = models.TextField() # Tag Description
tagSlug = models.TextField() # Extra info can be added to the existing tag using this field
class stores(models.Model):
storeName = models.CharField(max_length=15) # Store Name
storeDescription = models.TextField() # Store Description
storeURL = models.URLField() # Store URL
storePopularityNumber = models.IntegerField(max_length=1) # Store Popularity Number
storeImage = models.ImageField(upload_to=storeImageDir) # Store Image
storeSlug = models.TextField() # This is the text you see in the URL
createdAt = models.DateTimeField() # Time at which store is created
updatedAt = models.DateTimeField() # Time at which store is updated
storeTags = models.ManyToManyField(tags)
class tagsAdmin(admin.ModelAdmin):
list_display = ('tag', 'tagDescription', 'tagSlug')
class storesAdmin(admin.ModelAdmin):
list_display = ('storeName','storeDescription','storeURL',
'storePopularityNumber','storeImage',
'storeSlug','createdAt','createdAt','storeTags'
)
admin.site.register(tags,tagsAdmin)
admin.site.register(stores,storesAdmin)
Whenever I am trying to run command : python manage.py syncdb
I got the error: django.core.exceptions.ImproperlyConfigured: 'storesAdmin.list_display[8]', 'storeTags' is a ManyToManyField which is not supported.
I don't understand what I am doing wrong here. I want to simply display all the models in the django admin site.

You can't reference a Many2ManyField like that, you have to use a method instead in the stores class that looks like this
def get_tags():
return self.storeTags.all()
and reference that in your list_display(...'get_tags')
This is done because the M2M field would result in lots of SQL queries that would slow the entire thing down so therefore the choice would have to come from the developer and not from the framework.

Please check:
ModelAdmin.list_display
"ManyToManyField fields aren’t supported, because that would entail executing a separate SQL statement for each row in the table. If you want to do this nonetheless, give your model a custom method, and add that method’s name to list_display. (See below for more on custom methods in list_display.)"
You can use a custom method to show values of ManyToManyField or simply remove storeTags from list_display

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

Create a Blog which support multiple type of post

I am a new user of Django, and I am trying to figure out how to created a model which can support many kind (type) of elements.
This is the plot : I want to create a Blog module on my application.
To do this, I created a model Page, which describe a Blog Page. And a model PageElement, which describe a Post on the blog. Each Page can contain many PageElement.
A PageElement can have many types, because I want my users could post like just a short text, or just a video, or just a picture. I also would like (for example) the user could just post a reference to another model (like a reference to an user). Depending of the kind of content the user posted, the HTML page will display each PageElement in a different way.
But I don't know what is the right way to declare the PageElement class in order to support all these cases :(
Here is my Page model :
class Page(models.Model):
uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
# Basical informations
title = models.CharField(max_length=150)
description = models.TextField(blank=True)
# Foreign links
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True,
related_name='pages_as_user'
)
created_at = models.DateTimeField(default=timezone.now)
# Other fields ....
class Meta:
indexes = [
models.Index(fields=['uuid']),
models.Index(fields=['user', 'artist'])
]
For now, I have two solutions, the first one use inheritance : When you create a new post on the blog, you create an Element which inherit from PageElement model. Here are my different Models for each cases :
class PageElement(models.Model):
page = models.ForeignKey(
Page,
on_delete=models.CASCADE,
related_name='%(class)s_elements'
)
updated_at = models.DateTimeField(default=timezone.now)
created_at = models.DateTimeField(default=timezone.now)
class PageImageElement(PageElement):
image = models.ImageField(null=True)
image_url = models.URLField(null=True)
class PageVideoElement(PageElement):
video = models.FileField(null=True)
video_url = models.URLField(null=True)
class PageTextElement(PageElement):
text = models.TextField(null=True)
class PageUserElement(PageElement):
user = models.ForeignKey(
'auth.User',
on_delete=models.CASCADE,
related_name='elements'
)
This solution would be the one I have choosen if I had to work with "pure" Python. Because I could stored each PageElement in a dictionnary and filter them by class. And this solution could be easily extended in the futur with new type of content.
But with Django models. It seems that is not the best solution. Because it will be really difficult to get all PageElement children from the database (I can't just write "page.elements" to get all elements of all types, I need to get all %(class)s_elements elements manually and concatenate them :/). I have thinked about a solution like below (I don't have tried it yet), but it seems overkilled for this problem (and for the database which will have to deal with a large number of request):
class Page(models.Model):
# ...
def get_elements(self):
# Retrieve all PageElements children linked to the current Page
R = []
fields = self._meta.get_fields(include_hidden=True)
for f in fields:
try:
if '_elements' in f.name:
R += getattr(self, f.name)
except TypeError as e:
continue
return R
My second "solution" use an unique class which contains all fields I need. Depending of the kind of PageElement I want to create, I would put type field to the correct value, put the values in the corresponding fields, and put to NULL all other unused fields :
class PageElement(models.Model):
page = models.OneToOneField(
Page,
on_delete=models.CASCADE,
related_name='elements'
)
updated_at = models.DateTimeField(default=timezone.now)
created_at = models.DateTimeField(default=timezone.now)
TYPES_CHOICE = (
('img', 'Image'),
('vid', 'Video'),
('txt', 'Text'),
('usr', 'User'),
)
type = models.CharField(max_length=60, choices=TYPES_CHOICE)
# For type Image
image = models.ImageField(null=True)
image_url = models.URLField(null=True)
# For type Video
video = models.FileField(null=True)
video_url = models.URLField(null=True)
# For type Text
text = models.TextField(null=True)
# For type User
user = models.ForeignKey(
'auth.User',
on_delete=models.CASCADE,
related_name='elements',
null=True
)
With this solution, I can retrieve all elements in a single request with "page.elements". But it is less extendable than the previous one (I need to modify my entire table structure to add a new field or a new kind of Element).
To be honnest, I have absolutly no idea of which solution is the best. And I am sure other (better) solutions exist, but my poor Oriented-Object skills don't give me the ability to think about them ( :( )...
I want a solution which can be easily modified in the future (if for example, I want to add a new Type "calendar" on the Blog, which reference a DateTime). And which would be easy to use in my application if I want to retrieve all Elements related to a Page...
Thanks for your attention :)
I'm not sure it fits your problem but using GenericForeignKeys/ContentType framework may be appropriate in this case. It's quite powerful when one grasps the concept.
Example construct:
class Page(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
page_element = GenericForeignKey('content_type', 'object_id')
...
You can now connect any model object by the GenericFK to the Page model. So adding a new type (as a new model), at a later stage, is not intrusive.
Update:
As a comment pointed out this construct doesn't support many PageElements in a good way for a Page.
To elaborate, one way to solve that problem, still taking advantage of the GenericFK...
class PageElement(models.Model):
class Meta:
unique_together=('page', 'content_type', 'object_id') # Solve the unique per page
page = models.ForeignKey(Page, related_name='page_elements')
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
A Page can have many "abstract" PageElements and content_object is the "concrete PageElement model/implementation".
Easy to retrieve all elements for a specific page and allows inspection of the ContentType to check the type of element etc.
Just one way of many to solve this particular problem.
To establish the relationship between Page and PageElement in Django you would rather use Foreign Key relationship, than inheritance.
class PageImageElement(PageElement):
page = models.ForeignKey(Page,
on_delete=models.CASCADE,
related_name='images')
image = models.ImageField(null=True)
image_url = models.URLField(null=True)
Every user's post would create an instance of Page. Every addition of image to the Page would create an instance of PageImageElement and you could query for them using the related name. This way would be really easy to access all video, image, text modules of a single Page.
On a related note, I would say that PageElement class could be abstract see the docs and if you declare fields as possibly containing null values as in video = models.FileField(null=True) then it might be worth declaring blank=True as well, otherwise there will be errors when creating the object with these fields undefined. Discussed, for example, here: differentiate null=True, blank=True in django
I can't just write "page.elements" to get all elements of all types
Well actually, you can if you use multi-table inheritance. The problem is that all records returned are instances of PageElement, meaning you lose all information of the subclass type and the additional data these child objects may hold.
There are quite a lot of packages that tackle this polymorphism problem:
django packages: Model inheritance

Creating many to many relation with AUTH_USER_MODEL in django via intermediary model

I am trying to create the following models. There is a ManyToMany relation from Entry to AUTH_USER_MODEL via the EntryLike intermediate model.
class BaseType(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
creation_time = models.DateTimeField(auto_now_add=True)
last_update_time = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Title(BaseType):
text = models.CharField(max_length=100)
description = models.TextField()
class EntryLike(BaseType):
entry = models.ForeignKey(Entry)
user = models.ForeignKey(settings.AUTH_USER_MODEL)
class Entry(BaseType):
title = models.ForeignKey(Title, on_delete=models.PROTECT)
text = models.TextField()
user = models.ForeignKey(settings.AUTH_USER_MODEL)
liked_by_users = models.ManyToManyField(settings.AUTH_USER_MODEL, through='EntryLike', through_fields=('entry', 'user'))
Running migrations on the above model scheme throws the error: AttributeError:'str' object has no attribute 'meta'.
Any help in resolving this error would be highly appreciated. Am new to Django & Python, but not to Web Development.
The issue is that settings.AUTH_USER_MODEL is almost certainly not a model instance. It's probably a string that constrains the choices another model can make - settings would be a strange place to leave a model definition.
To do a MTM between the user model and your field above you need need to do:
from django.contrib.auth.models import User
class Entry(BaseType):
title = models.ForeignKey(Title, on_delete=models.PROTECT)
text = models.TextField()
user = models.ForeignKey(User)
def __str__(self):
return self.title
I've added the str function so that it gives a more sensible return when you're manipulating it in admin/shell.
I'd also question whether you need the second set of fields (removed here), as you can use select related between the Entry and EntryLike join table, without any duplication of the fields - you can probably go that way, it's just a bit unnecessary.
Lastly, I'd note that the way I'm using it above just uses the default User object that comes with Django - you may wish to customise it. or extend the base class as you've done here with your own models' base class.
(All of this is predicated on AUTH_USER_MODEL not being a model instance - if it is, can you post the model definition from settings.py? )

Django admin search and edit foreign fields

I've got a two part question regarding Django Admin.
Firstly, I've got a Django model Classified that has a foreign key field from another table Address. On setting data, I've got no issues with any of the fields and all fields get saved correctly.
However, if I want to edit the foreign field in the entry in Classified, it doesn't display the old/existing data in the fields. Instead it shows empty fields in the popup that opens.
How do I get the fields to display the existing data on clicking the + so that I can edit the correct information?
Secondly, I'm sure I've seen search fields in Django Admin. Am I mistaken? Is there a way for me to implement search in the admin panel? I have over 2 million records which need to be updated deleted from time to time. It's very cumbersome to manually go through all the pages in the admin and delete or edit those.
Adding Model Code:
Classified
class Classified(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=256)
contact_person = models.CharField(max_length=300, blank=True)
email = models.CharField(max_length=100, blank=True)
address = models.ForeignKey(Address)
subcategory = models.ForeignKey(Subcategory)
Address
class Address(models.Model):
id = models.AutoField(primary_key=True)
build_add = models.CharField(max_length=255)
street_add = models.CharField(max_length=255)
area = models.CharField(max_length=255)
city = models.ForeignKey(Cities)
The + means just that - add a new instance of the related object and relate the object you're editing to that. Because you're adding a new object it will be blank to start. If you want to be able to edit existing related objects from another object's admin you need to use inlines.
In your app's admin.py have something like:
from django.contrib import admin
from yourapp.models import Address, Classified
class AddressInline(admin.TabularInline):
model = Address
class ClassifiedAdmin(admin.ModelAdmin):
inlines = [AddressInline,]
admin.site.register(Classified, ClassifiedAdmin)
Adding search from there is really easy.
...
class ClassifiedAdmin(admin.ModelAdmin):
inlines = [AddressInline,]
search_fields = [
'field_you_want_to_search',
'another_field',
'address__field_on_relation',
]
...
Note the double underscore in that last one. That means you can search based on values in related objects' fields.
EDIT: This answer is right in that your foreignkey relationship is the wrong way round to do it this way - with the models shown in your question Classified would be the inline and Address the primary model.

python code for django view

MODEL:
class Pathology(models.Model):
pathology = models.CharField(max_length=100)
class Publication(models.Model):
pubtitle = models.TextField()
class Pathpubcombo(models.Model):
pathology = models.ForeignKey(Pathology)
publication = models.ForeignKey(Publication)
List of pathology sent to HTML template as drop down menu
VIEW:
def search(request):
pathology_list = Pathology.objects.select_related().order_by('pathology')
User selects one pathology name from drop down menu and id retrieved by
VIEW:
def pathology(request):
pathology_id = request.POST['pathology_id']
p = get_object_or_404(Pathology, pk=pathology_id)
Where I'm stuck. I need the python/django syntax to write the following:
The pathology_id must now retrieve the publication_id from the table Pathpubcombo (the intermediary manytomany table). Once the publication_id is retrieved then it must be used to retrieve all the attributes from the publication table and those attributes are sent to another html template for display to the user.
you should be using many-to-many relations as described here:
http://www.djangoproject.com/documentation/models/many_to_many/
Like:
class Pathology(models.Model):
pathology = models.CharField(max_length=100)
publications = models.ManyToManyField(Publication)
class Publication(models.Model):
pubtitle = models.TextField()
Then
def pathology(request):
pathology_id = request.POST['pathology_id']
p = get_object_or_404(Pathology, pk=pathology_id)
publications = p.publications.all()
return render_to_response('my_template.html',
{'publications':publications},
context_instance=RequestContext(request))
Hope this works, haven't tested it, but you get the idea.
edit:
You can also use select_related() if there is no possibility to rename tables and use django's buildin support.
http://docs.djangoproject.com/en/dev/ref/models/querysets/#id4

Categories

Resources