manytomany field not working django-cms - python

I am using django-cms
many to many field is working fine when i add plugins or update but
after publish page i didn't get any data where i add many to many field.
models are look like this
#python_2_unicode_compatible
class ClientLogo(CMSPlugin):
client_logo = models.ManyToManyField(LogoPluginModel, blank=True)
class LogoPluginModel(CMSPlugin):
title = models.CharField(max_length=100)
here field 'client_logo' will be disapper when i publish djagno-cms page

The relations need to be explicitly copied through the copy_relations method (see django-cms models manual). It's also advantageous to add a related_name property to the ManyToManyField, especially when a model contains multiple sets of foreign keys or ManyToManyFields.
#python_2_unicode_compatible
class ClientLogo(CMSPlugin):
client_logo = models.ManyToManyField(
LogoPluginModel,
blank=True,
related_name='client_logos',
)
class LogoPluginModel(CMSPlugin):
title = models.CharField(max_length=100)
def copy_relations(self, oldinstance):
self.client_logos.all().delete()
for logo in oldinstance.client_logos.all():
logo.pk = None
logo.showroom = self
logo.save()

Related

Django unique together relationship with field and manytomany on self

I'm try create post with language and content, and relate it on other versions of same page, but I'm get stuck
class Page(models.Model):
content = models.TextField()
language = models.CharField(max_length=7, choices=settings.LANGUAGES)
versions = models.ManyToManyField('self', blank=True)
class Meta:
unique_together = ('language', 'versions',)
This will not work properly, because Django not allow make "unique" ManyToMany fields.
Then I'm try make same relationship trough related model:
class VersionsPage(models.Model):
pass
# ToDo: add unique together here, to foreign key field
class Page(models.Model):
...
versions = models.ManyToManyField('self', blank=True, through="VersionsPage")
Anyone know how to make that without using symmetrical=False?
I think you are looking for something like this:
class Page(models.Model):
pass
class PageVersion(models.Model):
page = models.ForeignKey(Page, related_name='versions')
content = models.TextField()
language = models.CharField(max_length=7, choices=settings.LANGUAGES)
class Meta:
unique_together = ('page', 'language',)
#getting all page versions:
page = Page.objects.get(pk=some_id)
versions = page.versions.all()

Django reference a Model by foreign key or a different field

I am using Django REST Framework. I have two models, Sites and Statuses.
class Sites(models.Model):
site_id = models.AutoField(primary_key=True)
status = models.ForeignKey(Statuses, models.DO_NOTHING, blank=True, null=True)
class Statuses(models.Model):
status_id = models.AutoField(primary_key=True)
description = models.CharField(max_length=255, blank=True, null=True, unique=True)
class Meta:
managed = True
db_table = 'Statuses'
I would like to be able to perform a GET on sites, and have the Statuses.description field returned (instead of Statuses.status_id). Also, I would like it so that either status_id or description may be used interchangeably in a POST to create a new site. Where does this type of functionality belong (serializer, models, etc...)?
I know I can accomplish the first part of my question by adding a property to the Sites model and then referencing this field in the Sites serializer.
#property
def status(self):
return self.row_status.description
However I thought the convention of a Model is that it should be a 1:1 representation of the database table. Is there a better way to do this?
This fits well in the serializer, like this:
class SitesSerializer(serializers.ModelSerializer):
description = serializers.CharField(source='status.description')
class Meta:
model = Sites
fields = ('site_id', 'description')
(But the status field should probably not have null=True set.)

Django: allow user to add fields to model

I am just starting with Django and want to create a model for an application.
I find Djangos feature to
- automatically define validations and html widget types for forms according to the field type defined in the model and
- define a choice set for the field right in the model
very usefull and I want to make best use of it. Also, I want to make best use of the admin interface.
However, what if I want to allow the user of the application to add fields to the model? For example, consider a simple adress book. I want the user to be able to define additional atributes for all of his contacts in the admin settings, i.e. add a fax number field, so that a fax number can be added to all contacts.
from a relational DB perspective, I would have a table with atributes (PK: atr_ID, atr_name, atr_type) and an N:N relation between atributes and contacts with foreign keys from atributes and contacts - i.e. it would result in 3 tables in the DB. right?
but that way I cannot define the field types directly in the Django model. Now what is best practice here? How can I make use of Djangos functionality AND allow the user to add aditional/custom fields via the admin interface?
Thank you! :)
Best
Teconomix
i would suggest storing json as a string in the database, that way it can be as extendable as you want and the field list can go very long.
Edit:
If you are using other damn backends you can use Django-jsonfield. If you are using Postgres then it has a native jsonfield support for enhanced querying, etc.
Edit 2:
Using django mongodb connector can also help.
I've used this approach, first seen in django-payslip, to allow for extendable fields. This provides a structure for adding fields to models, from which you can allow users to add/edit through standard view procedures (no admin hacking necessary). This should be enough to get you started, and taking a look at django-payslip's source code (see the views) also provides view Mixins and forms as an example of how to render to users.
class YourModel(models.Model):
extra_fields = models.ManyToManyField(
'your_app.ExtraField',
verbose_name=_('Extra fields'),
blank=True, null=True,
)
class ExtraFieldType(models.Model):
"""
Model to create custom information holders.
:name: Name of the attribute.
:description: Description of the attribute.
:model: Can be set in order to allow the use of only one model.
:fixed_values: Can transform related exta fields into choices.
"""
name = models.CharField(
max_length=100,
verbose_name=_('Name'),
)
description = models.CharField(
max_length=100,
blank=True, null=True,
verbose_name=_('Description'),
)
model = models.CharField(
max_length=10,
choices=(
('YourModel', 'YourModel'),
('AnotherModel', 'AnotherModel'), # which models do you want to add extra fields to?
),
verbose_name=_('Model'),
blank=True, null=True,
)
fixed_values = models.BooleanField(
default=False,
verbose_name=_('Fixed values'),
)
class Meta:
ordering = ['name', ]
def __unicode__(self):
return '{0}'.format(self.name)
class ExtraField(models.Model):
"""
Model to create custom fields.
:field_type: Connection to the field type.
:value: Current value of this extra field.
"""
field_type = models.ForeignKey(
'your_app.ExtraFieldType',
verbose_name=_('Field type'),
related_name='extra_fields',
help_text=_('Only field types with fixed values can be chosen to add'
' global values.'),
)
value = models.CharField(
max_length=200,
verbose_name=_('Value'),
)
class Meta:
ordering = ['field_type__name', ]
def __unicode__(self):
return '{0} ({1}) - {2}'.format(
self.field_type, self.field_type.get_model_display() or 'general',
self.value)
You can use InlineModelAdmin objects. It should be something like:
#models.py
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=100)
class ContactType(models.Model):
name = models.CharField(max_length=100)
class Contact(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
contact_type = models.ForeignKey(ContactType, on_delete=models.CASCADE)
value = models.CharField(max_length=100)
#admin.py
from django.contrib import admin
class ContactInline(admin.TabularInline):
model = Contact
class PersonAdmin(admin.ModelAdmin):
inlines = [
ContactInline,
]
By the way... stackoverflow questions should contain some code. You should try to do something before asking a question.

Retrieve Django rest framework related fields

Using the django-rest-framework is it possible to retrieve content from a related field. So for example I want to create a genre list which contains all projects within it. This is what I have but I keep on getting the error:
'Genre' object has no attribute 'project_set'
models.py
class Genre(models.Model):
name = models.CharField(max_length=100, db_index=True)
class Project(models.Model):
title = models.CharField(max_length=100, unique=True)
genres = models.ManyToManyField(Genre, related_name='genres')
serializers.py
class GenreSerializer(serializers.ModelSerializer):
project_set = serializers.ManyRelatedField()
class Meta:
model = Genre
fields = ('name', 'project_set')
The related name you're using on the Project class is badly named. That related name is how you access the set of projects related to a given genre instance. So you should be using something like related_name='projects'. (As it is you've got it the wrong way around.)
Then make sure that your serializer class matches up with the related name you're using, so in both places project_set should then instead be projects.
(Alternatively you could just remove the related_name='genres' entirely and everything will work as you were expecting, as the default related_name will be 'project_set'.)

Use a class before its definition in Django model

When I try to syncdb I get the error Menu is not a valid class Name.
How can I resolve that relationship case :
class MenuItem(model.Models)
title = models.CharField(max_length=200)
submenus = models.ManyToManyField(Menu, blank=True, null=True)
class Menu(Container):
links = models.ManyToManyField(MenuItem)
From the Django book:
If you need to create a relationship on a model that has not yet been
defined, you can use the name of the model, rather than the model
object itself:
E.g.:
class MenuItem(model.Models)
title = models.CharField(max_length=200)
submenus = models.ManyToManyField('Menu', blank=True, null=True)
^ ^
Edit:
As Francis mentions (and as is written in the documentation):
It doesn't matter which model has the ManyToManyField, but you should only put it in one of the models -- not both.
One of these models has a many to many, the other one uses Django's reverse relations (https://docs.djangoproject.com/en/dev/topics/db/queries/#following-relationships-backward)
So how I would set it up:
class Menu(Container):
links = models.ManyToManyField(MenuItem)
class MenuItem(model.Models)
title = models.CharField(max_length=200)
Then when I wanted a MenuItem's Menus:
menu_item_instance.menu_set.all()

Categories