Import app foreign key model class in another app model - django

I know there are other similar questions, but I have a specific case:
Right now there are two apps:
-prev_app
-new_app
prev_app contains a "product" model.
new_app contains "store" and "contract" model.
"store" model has a manytomanyfield to "product" model
"contract" is a intermediary model for "store" and "product"
..
.
So now what I want to do is to put that "product" model into the new_app, (so all related models are in one app) but I just don't know how to proceed with the migrations.
Any thoughts?

put db_table to your model and move it wherever you want. it refers then always to that old db table and you dont need any migrations for your new app.
class Product(models.Model):
class Meta:
db_table = 'oldapp_tablename'
just be careful that imports should be adjusted according to new layout.

Related

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?

Including fields from a OneToOneField in Django Admin

I am attempting to add the fields from a OneToOneField into my admin view. Here is an example of how my models look.
class Customer(BaseUser):
name = CharField()
address = CharField()
secondary_information = OneToOneField("SecondaryCustomerInfo", on_delete=SET_NULL, null=True)
class SecondaryCustomerInfo(models.Model):
email = EmailField()
And I tried adding in the fields as an inline like this.
class SecondaryCustomerInfoInline(admin.StackedInline):
model = SecondaryCustomerInfo
class CustomerAdmin(admin.ModelAdmin):
inlines = [SecondaryCustomerInfoInline]
But I get the error
<class 'user.admin.SecondaryCustomerInfoInline'>: (admin.E202) 'user.SecondaryCustomerInfo' has no ForeignKey to 'user.Customer'.
I'm used to putting the OneToOneField on the secondary model but my coworker asked that I put it on the main Customer model since we will be accessing that information more often. I think switching things around is what is tripping me up. How would I include the fields from SecondaryCustomerInfo on the admin view for Customer?
The answer would be to use Django Reverse Admin
From its documentation:
Module that makes django admin handle OneToOneFields in a better way. A common use case for one-to-one relationships is to "embed" a model inside another one. For example, a Person may have multiple foreign keys pointing to an Address entity, one home address, one business address and so on. Django admin displays those relations using select boxes, letting the user choose which address entity to connect to a person. A more natural way to handle the relationship is using inlines. However, since the foreign key is placed on the owning entity, django admins standard inline classes can't be used.
class CustomerAdmin(ReverseModelAdmin):
inline_type = 'stacked'
inline_reverse = ['secondary_information']

Add a unique "intermediary" model to all my Django ManyToManyField()

Hello Awesome People!
Such a question that I have made a lot of searches for it. I am done building a website two(2) months ago, but today The team decides to track every time an instance has been added to a Model in ManyToManyField() fields.
I was thinking using the through argument to point to the model that will act as an intermediary may work but not at all in my case (70%). Just Because I want to have a unique intermediary model that will record for all ManyToManyField()
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateTimeField(auto_now_add=True)
Ah! Something is required. I need to explicitly specify foreign keys to the models that are involved in the many-to-many relationship.
Django ContentType may anticipate for all my models, but it's not working, I wonder why? it also contains ForeignKey (the one required by an intermediary model).
Do I really need to edit all my ManyToManyField fields and create Model as much as ManytoManyField? is there a way to record date_joined without creating an intermediary model for each?
Are you perhaps looking for something like django admin's LogEntry model?
LogEntry contains the ContentType of the model instance that has changed, the id of the instance, the type of change and an abstract change message. With all of that you can retrace changes made to instances.
In django admin, the views take care of adding records to LogEntry via three methods log_change/addition/deletion: click.

django_comments adding new field in the model

I am trying to add a new field in django_comment model. According to the documentation, most custom comment models will subclass the CommentAbstractModel model:
from django.db import models
from django_comments.models import CommentAbstractModel
class CommentWithTitle(CommentAbstractModel):
title = models.CharField(max_length=300)
If I generate a migration, then it adds all the fields into migrations (all fields from comment model plus title field).
And after running migrations, CommentWithTitle table and django_comments table are created. But django_comments would be useless (not in use).
Another approach is to generate the table this way:
from django_comments.models import Comment
class CommentWithTitle(Comment):
title = models.CharField(max_length=300)
And it generates the migration with one field only with the reference of comment_ptr.
My Question is: which approach is better? I think the first model is good as it has all fields in one table. But that generates the django_model which is not in use at all.
I would follow the documentation.
Looking at the implementation, Comment is basically just extending CommentAbstractModel with db_table specified.
class Comment(CommentAbstractModel):
class Meta(CommentAbstractModel.Meta):
db_table = "django_comments"
I'm suspecting that if you do the second option you mentioned, the migration would throw an error because the db_table will be created twice.

Django using a ManytoMany as a Foreign Key

I'm trying to use a many to many relation as a foreign key for another table, but I'm not sure if this is possible.Consider the following model:
from django.db import models
class Attribute(models.Model):
name=models.CharField(max_length=30)
unit=models.CharField(max_length=30)
class Protocol(models.Model):
name=models.CharField(max_length=30)
attributes=models.ManyToManyField(Attribute,db_table='protocol_attribute')
class Device(models.Model):
serial_number = models.CharField(max_length=30)
id_protocol=models.ForeignKey(Protocol)
class DeviceValues(models.Model):
id_device=models.ForeignKey(Device)
id_protocol_attribute=models.ForeignKey(Protocol.attributes)
value=models.IntegerField()
When I try to validate this model I receive the following error:
First parameter to ForeignKey must be either a model, a model name, or the string 'self'
I know I am not using a model or a model name as the first parameter, but how can I reference as a foreign key the join table that Django will automatically create that handles the mapping between Protocol and Attributes?
A possible workaround could be to add the protocol as a foreign key to the Attribute class and then use the attribute as a foreing key to the DeviceValue class. However, I don't want to do that because I will have protocols that will be sharing attributes. I would prefer to make the join table rather that repeating attributes for each protocol.
Any ideas will be more than welcome....thanks!!!
Alejandro
Using an intermediate table, I solved it. The model ended up like this.
from django.db import models
class Attribute(models.Model):
name=models.CharField(max_length=30)
unit=models.CharField(max_length=30)
class Protocol(models.Model):
name=models.CharField(max_length=30)
attributes=models.ManyToManyField(Attribute,through='DeviceValue')
class Device(models.Model):
serial_number = models.CharField(max_length=30)
id_protocol=models.ForeignKey(Protocol)
class DeviceValue(models.Model):
id_name=models.ForeignKey(Protocol)
id_attribute=models.ForeignKey(Attribute)
id_device=models.ForeignKey(Device)
value=models.IntegerField()
One thing worth mention is that when using sqlall the UNIQUE constraint for the three foreign keys of the DeviceValue tablue was not generated, so I just added it before creating the database.