Add a GenericRelation in a Proxy Model - django

I have a group of models in django 1.5.2 that all use GenericForeignKey and GenericRelation. The problem is that I also use proxy inheritance. A generic relation is a Field, but not a DB field, but when validating the model, django sees a Field in a proxy inherited model and raises an error.
Below is a simplified version of my problem. Is there a simple solution that would allow me to access simply the tags from TaggableArticle ?
from django.db import models
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
class Tag(models.Model):
tag = models.SlugField()
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
class Article(models.Model):
text = models.TextField()
class TaggableArticle(Article):
tags = generic.GenericRelation(Tag)
class Meta:
proxy = True
The result is :
python manage.py validate
FieldError: Proxy model 'TaggableArticle' contains model fields.
[1] 15784 exit 1 python manage.py validate
My thoughts so far :
django 1.6 introduces a for_concrete_model flag in generic relations, but I haven't been able to see if this could solve my problem. I just understood that it could help if the relation was in Article, and if I wanted to be able to tag an object with the proper content type (Article vs TaggedArticle).
I could remove the relation and just access it from the other endpoint (i.e. `Tag.objects.filter(content_object=myTaggedArticle) or manually add a method to this) but part of the implementation I have integrates the fact I'm using a RelatedManager and not just a normal Manager, and I would not be getting a related manager if I came from the whole TaggedArticle class.
Tkank you !

Related

Is there a way to create a django model foreignkey field with variable choices?

Let's say I have three models device, mechanical and digital. In the device model I have a field type. The type field needs to be in a foreign key relationship with either mechanical or digital model which will be determined by the data. Is there any way to create the type field in such a way that the model in which the foreign key relationship is to be done can be chosen manually.
Something like:
type = models.ForeignKey(to=Choices)
where the Choices could be digital and mechanical.
I have tried implementing generic foreign keys but my database schema is a bit complex so that would be very difficult to maintain. Is there any other way in django that I can do the above?
A generic way that you can manage this would be to use your own models.
Create a ChoiceItemGroup model, slug, name, description.
Create another model ChoiceItem, with slug, name, description, and FK to ChoiceItemGroup.
Then you can do:
type=models.ForeignKey(ChoiceItem, on_delete=models.CASCADE)
Then you can create generic choices and generic choice groups by registering the models in the admin panel
Adding a foreign key from one of your own models to ContentType allows your model to effectively tie itself to another model class, But it’s possible to go one step further and use ContentType to enable truly generic (sometimes called “polymorphic”) relationships between models.
For example, it could be used for a tagging system like so:
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
class TaggedItem(models.Model):
tag = models.SlugField()
content_type = models.ForeignKey(ContentType,
on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
def __str__(self):
return self.tag
Django generic relations

How to use foreignkey with different models in DJango

I'm stack with this problem, and looking for some solution before asking this question here. Lets say I have a one Model that shares same field in different Models how can I achieve this that when I get the objects of those Models I can include that Model foreign key, I did try to achieve this using Generic Relation in DJango yet it didn't solve my issue.
here is the sample what I'm trying to achieve using Generic Relation:
Model1(models.Model):
.. objects_on_this_model ..
Model2(models.Model):
.. objects_on_this_model ...
# Now this is where the model I could save different models with same field shared
SameObjectModel(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntengerField()
content_object = GenericForeignKey('content_type', 'object_id')
.. objects_on_this_model .. # which is the field that has same field to use in different models
So when I try to get the objects from Model(n) how can I achieve or get the SameObjectModel?
I have this on my mind that I could do this:
Model(n).objects.prefetch_related('fk').all()
Seems it is not a good idea, since I do not know where I should put the related_name since the foreign key is the content_type which is the model and there is the object_id represent the field primary_key.
On your Model(n)'s you can add a GenericRelation to SameObjectModel:
from django.contrib.contenttypes.fields import GenericRelation
class Model1(models.Model):
sameobject = GenericRelation(SameObjectModel)
With this, it should be possible to use prefetch_related:
Model1.objects.prefetch_related('sameobject').all()

How to skip dummy model from django test

I have created one django admin page which is associated with a dummy model which doesn't exists.
Here is the code. The statistic model doesn't exists in database.
class StatisticModel(models.Model):
class Meta:
verbose_name_plural = 'Statistic'
class StatisticModelAdmin(admin.ModelAdmin):
model = StatisticModel
def get_urls(self):
view_name = 'changelist'
return [
path('settings/', my_custom_view, name=view_name),
]
admin.site.register(StatisticModel, StatisticModelAdmin)
In my git workflow I have below command,
python backend/django/manage.py test ./backend/django
Which is failing with error,
django.db.utils.ProgrammingError: relation "monitor_statisticmodel" does not exist
Please advise how can I avoid or skip this error?
https://docs.djangoproject.com/en/3.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_urls
This allows you to create admin pages with custom views without requiring models.
Before my answer: why bother have this model if it's not going to be used? If it's only there for testing, write "abstract = True" in the Meta class. If you don't want to do that then...
Maybe setting abstract=True would work? I'm not sure it will since Django's ModelAdmin might raise an error. What I'd advise is Django doesn't is setting "IS_TESTING" in your settings file. Imo, you should have multiple settings file. Then your model can look like:
class StatisticModel(models.Model)
class Meta:
verbose_name_plural = "Statistic"
abstract = getattr(settings, "IS_TESTING", False)
Another example is via a monkey patch and assuming that model is in admin.py. So during your test case, you can run this before your tests begin:
from project import admin
admin.StatisticModel.Meta.abstract = True

Using Djongo's ArrayField at Django Admin

Djongo is a Django and MongoDB database connector witch brings, beside others, the ArrayField to Django Models. It allows one to store multiple instances of an other djongo.models.Model in an unique MongoDB Array field inside a document related with the Model that has the Arrayfield
As described in source documentation:
"The model of the container must be declared as abstract, thus should not be treated as a collection of its own."
As well as in djongo's site tutorials
"In case you don’t plan on using your embedded model as a standalone model (which means it will always be embedded inside a parent model) you should add the class Meta and abstract = True This way Djongo will never register this model as an actual model."
This way I made:
# models.py
class Contact(models.Model):
key = models.CharField(max_length=100)
class Meta:
abstract = True
class ContactForm(forms.ModelForm):
class Meta:
model = Contact
fields = ('key',)
class Person(models.Model):
_id = models.ObjectIdField()
...
contact = models.ArrayField(
model_container=Contact,
model_form_class=ContactForm,
)
objects = models.DjongoManager()
# admin.py
admin.site.register(Person)
$ pip freeze
Django==3.2.4
djongo==1.3.6
pymongo==3.11.4
...
However when I try to add a Person through Django Admin (in /admin/<app>/person/add/) I receive the error Abstract models cannot be instantiated from .../django/db/models/base.py
This seems inconsistent with Djongo's description. Am I doing something wrong?

How to put allow for two different content types as argument in admin

I'm a Django and DB noob, but I'm working on a website that has both blogs and articles. They are instantiated in admin in their own respective fields and basically I have a class "FeaturedPost" in model.py where for one of the attributes "content" I want to be able to pick from the available blogs or articles.
I'm aware that if I want to map the content to a blog, I would do a
models.ForeignKey(Blogs, related_name="w/e")
but how do I abstract this so I can pick from the two content types? Would a GenericForeignKey be helpful?
I'm using Fein-CMS if that helps with anything in this case.
Correct, GenericForeignKey is what you need. i.e.
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class FeaturedPost(models.Model):
...
content_type = models.ForeignKey(ContentType)
content_object_id = models.PositiveIntegerField()
content = GenericForeignKey('content_type', 'content_object_id')
To edit these in the admin, you'll need to use a generic inline