Let's assume I have this models structure:
class User(AbstractUser):
first_name = models.CharField(max_length=40, blank=True)
last_name = models.CharField(max_length=40, blank=True)
class UserProfile(models.Model):
uuid = models.UUIDField(unique=True, null=False, default=uuid4)
user = models.OneToOneField(User)
I would like to merge UserProfile into User model, like this:
class User(AbstractUser):
first_name = models.CharField(max_length=40, blank=True)
last_name = models.CharField(max_length=40, blank=True)
uuid = models.UUIDField(unique=True, null=False, default=uuid4)
Most important thing is to migrate existing uuid from UserProfile model to new User.uuid (unique) field. How should that be managed in django > 1.7 migrations ?
First, add the uuid field to the User model. Create a migration.
Then, create a data migration and add a RunPython operation to call a function that copies the data from the old to the new models. Something like:
def copy_uuid(apps, schema_editor):
User = apps.get_model("myapp", "User")
# loop, or...
User.objects.update(uuid=F("userprofile__uuid"))
class Migration(migrations.Migration):
dependencies = []
operations = [
migrations.RunPython(copy_uuid),
]
Once you've migrated and are sure that everything worked, you can delete the UserProfile model in another migration.
Related
I am trying to migrate, and view the admin page. both makemigrations and migrate passed, yet when i go to the admin url it reads this: "django.db.utils.OperationalError: no such column: social_app_user.id"
And once i create an id field, it changes to "django.db.utils.OperationalError: no such column: social_app_user.password"
I was under the impression that the AbstractUser model included all the default user fields, not sure about the primary key, but regardless.
Please help, thanks!
Note: the 'id' field in this models.py file was added after i got the error.
from django.contrib.auth.models import AbstractUser, UserManager
from django.db import models
class User(AbstractUser):
is_verified = models.BooleanField(default=True)
id= models.AutoField(primary_key=True, null=False)
REQUIRED_FIELDS = []
objects = UserManager()
def __str__(self):
f"{self.username} {self.email}"
return
class main_feed(models.Model):
content= models.CharField(unique=True, max_length=255, default='', null=False)
poster = models.ForeignKey('User', related_name='author', on_delete=models.CASCADE, to_field='username')
likes = models.IntegerField(default=0, null=False)
favorites = models.IntegerField(default=0, null=False)
date_posted = models.DateTimeField(auto_now=True)
def __str__(self):
f"{self.content} {self.likes} {self.poster} {self.date_posted}"
return
It turns out I had to restart my entire application and run startapp again.
This time i added the user model and set up the settings and admin file BEFORE the very first migration. then everything works dandy. But I have no idea why this is the case, shouldnt the migration update and override the default user model?
anyways the question is answered now.
I am trying to import data from an csv file into a django db using django-import-export. My problem is trying to upload data with a ForeignKey as an object. I have migrated, followed docs, and still no solution. You can see my error below in the django admin:
Here is my csv data with a blank 'Id' column:
models.py
from django.db import models
from django.shortcuts import reverse
from urllib.parse import urlparse
class States(models.Model):
name = models.CharField(max_length=96, blank=False, unique=True)
abbrv = models.CharField(max_length=2, null=True, blank=True)
class Meta:
ordering = ['name']
verbose_name = 'State'
verbose_name_plural = 'States'
def __str__(self):
return f'{self.name}'
class Person(models.Model):
last_name = models.CharField(
max_length=255, help_text="Enter your last name.")
first_name = models.CharField(
max_length=255, help_text="Enter your first name or first initial.")
address = models.CharField(
max_length=255, blank=True, help_text="Enter your street address.")
city = models.CharField(
max_length=255, blank=True, help_text="Enter your city.")
state = models.ForeignKey('States', to_field='name', on_delete=models.SET_NULL, null=True)
zipcode = models.CharField(max_length=50)
website = models.URLField(
max_length=255, blank=True)
profession = models.CharField(max_length=50, blank=True)
# META CLASS
class Meta:
verbose_name = 'Person'
verbose_name_plural = 'Persons'
ordering = ['last_name', 'first_name']
# TO STRING METHOD
def __str__(self):
"""String for representing the Model object."""
return f'{self.last_name}, {self.first_name}'
admin.py:
from django.contrib import admin
from .models import Person, States
from import_export.admin import ImportExportModelAdmin
from import_export.widgets import ForeignKeyWidget
from import_export import fields, resources
class PersonResource(resources.ModelResource):
state = fields.Field(
column_name='state',
attribute='state',
widget=ForeignKeyWidget(States, 'name'))
class Meta:
model = Person
class PersonAdmin(ImportExportModelAdmin):
list_display = ('last_name', 'first_name', 'state')
search_fields = ('first_name', 'last_name' )
resources_class = PersonResource
admin.site.register(Person, PersonAdmin)
admin.site.register(States)
I think you need to specify both in your question here, as well as to Django how you want the id field treated.
Do you want it propagated with the Django id or pk (sometimes the same sometimes not)? Then you would have id=self.id or id=self.pk somewhere in your view for the datatable.
Do you want your database to create a unique key?
You would need to add some functionality someplace to tell Django how to fill in that field.
Also, if you want it to create an id different from the Django id or pk then you would need to add the field to your model.
https://docs.djangoproject.com/en/3.1/ref/forms/validation/
https://docs.djangoproject.com/en/3.1/ref/validators/
https://docs.djangoproject.com/en/3.1/ref/forms/api/
Or, perhaps after Validation of the form, when you create the object. Add something to the effect of id=[database function to create unique id].
Another solution might be a templateTag or templateFilter to create a value on the form side if you want to create the id based on info contained in the form. Like combining last 4 of name with time of submission.
https://docs.djangoproject.com/en/3.1/ref/templates/builtins/
https://docs.djangoproject.com/en/3.1/howto/custom-template-tags/
Having just re-read your question, also, I'm not sure but you might be asking if the database can support an embedded reference to another object. Is ID a reference to another model's key? That's a whole different question. And it is database specific.
Last Suggestion: Perhaps a re-read of:
https://docs.djangoproject.com/en/3.1/ref/forms/fields/#fields-which-handle-relationships
This error is occur because your id did not received an id or int value it received a str type of value Wyoming try to pass int value in id
Update
just update your PersonResource Meta class like this
class PersonResource(resources.ModelResource):
state = fields.Field(
column_name='state',
attribute='state',
widget=ForeignKeyWidget(States, 'name'))
class Meta:
model = Person
import_id_fields = ['id']
The default field for object identification is id, you can optionally
set which fields are used as the id when importing
check official doc. for more information.
I have nested models with OneToOneFields and want to have an InlineModelAdmin form in one ModelAdmin to point to a nested model...
models.py:
class User(models.Model):
username = models.CharField(max_length=128)
password = models.charField(max_length=128)
class IdentityProof(models.Model):
user = models.OneToOneField(User, on_delete=models.PROTECT, related_name='proof')
proof_identity = models.FileField(upload_to='uploads/%Y/%m/%d/')
class Company(models.Model):
user = models.OneToOneField(User, on_delete=models.PROTECT, related_name='company')
name = models.CharField(max_length=128)
class Person(models.Model):
user = models.OneToOneField(User, on_delete=models.PROTECT, related_name='person')
name = models.CharField(max_length=128)
admin.py:
class IdentityProofInline(admin.TabularInline):
model = IdentityProof
#admin.register(Company)
class CompanyAdmin(admin.ModelAdmin):
inlines = [IdentityProofInline]
#admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
inlines = [IdentityProofInline]
For CompanyAdmin or PersonAdmin, I want to show its User's IdentityProof. How can I do that ?
I tried to use fk_name = 'user_proof or other combinations but it doesn't work...
Thanks.
This is not possible without an external package.
See Django Nested Inline and Django Nested Admin
I am trying to build relations with my database tables. Im having a tutorial lesson at the moment with 3 tables. for example (auth_user table, partyEvent table, friends table).
Now a user should be able to create just one partyEvent. Friends can join any number of partyEvent created by the users.
The owner id in the Friends model tells the partyEvent and User 'the friend' belongs to.
I am able to restrict the users to create only one partyEvent. But when i try to register friends to a partyEvent, the owner's id is not sent. Instead the default value in:
owner = models.OneToOneField('auth.User', related_name = 'party', on_delete=models.CASCADE, default='1')
is rather sent. Why is that happening?
models
class PartyEvent(models.Model):
name = models.CharField(max_length=100, blank=False)
location = models.CharField(max_length=100, blank=False)
owner = models.OneToOneField('auth.User', related_name = 'party', on_delete=models.CASCADE, default='1')
class Friends(models.Model):
name = models.CharField(max_length=100, blank=False)
owner = models.ForeignKey('auth.User',related_name = 'friends', on_delete=models.CASCADE, default='1')
serializers
class FriendsSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.id')
class Meta:
model = Friends
fields = ('id','name','owner')
You can set current user by assigning serializers.CurrentUserDefault() as your serializer field default. Here is an example from the doc:
owner = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
I am working with some legacy database models in a Django REST Framework application:
class Variable(models.Model):
var_id = models.AutoField(primary_key=True)
resource_type = models.CharField(max_length=1, blank=True, null=True)
resource_id = models.BigIntegerField(blank=True, null=True)
var_name = models.CharField(max_length=500, blank=True, null=True)
class Meta:
managed = False
db_table = 'variables'
class Project(models.Model):
project_id = models.AutoField(primary_key=True)
name = models.CharField(unique=True, max_length=100, blank=True, null=True)
class Meta:
managed = True
db_table = 'projects'
Project and Variable are related models such that when the resource_type of a Variable is 'P', then its resource_id represents the project_id of the Project it belongs to. If the resource_type is something other than 'P, then that Variable belongs to a different type of model. I unfortunately can not make significant changes to the database schema for these models.
Is there a way to define a custom relationship between these two models so that I can treat them as if Variable was defined with a ForeignKey to Project? Or as if Project has a ManyToManyField relationship to Variable? I'd ultimately like to be able to create a nested serializer relationship. Something like:
class Variable(serializers.ModelSerializer):
class Meta:
model = models.Variable
fields = ('var_id', 'resource_type', 'resource_id', 'var_name')
class ProjectSerializer(serializers.ModelSerializer):
variables = VariableSerializer(many=True)
class Meta:
model = models.Project
fields = ('project_id', 'name', 'variables')
Thanks!