Django admin set fk_name = to_field in inline class only allows one image to be uploaded

I am new to Django and I ran into a problem when I tried enable the admin to add multiple images to a user profile at once.

I created a Model Profile that allows a user to have one profile, and each profile has more than one photo.

I want to use user_id to link photos to profile and use user_id for filter. However, when I tried to upload more than one photo to a profile, it displays error “Please correct the errors below.”

The following are my models and classes I added to the admin.py

models.py

    class Profile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL,
                on_delete=models.SET_NULL, null=True,
                )

    GENDER_CHOICES = (
        ('F', 'Female'),
        ('M', 'Male')
        )
    date_of_birth = models.DateField(blank=True, null=True)
    gender = models.CharField(max_length=1, 
        default='F',
        blank=False,
        choices=GENDER_CHOICES
        )       
    about_me = SizedTextField(
        size_class=2, 
        null=True,
        blank=True
        )
    date_created = models.DateTimeField(default=timezone.now)          


class Photos(models.Model):
    user = models.ForeignKey(
        Profile,
        to_field='user',
        null=True, 
        blank=True,
        on_delete=models.SET_NULL
        )
    photo = models.ImageField(
        upload_to='photos/%Y/%m/%d/',
        blank=True
        )
admin.py


class PhotosInline(admin.TabularInline):
    model = Photos
    fk_name = 'user'#  only one photo allowed to be uploaded when I specify this, I want more than one


@admin.register(Profile)
class ProfileAdmin(admin.ModelAdmin):
    list_display = ['user', 'date_of_birth','gender', 'about_me']
    inlines = [PhotosInline,]

Why does it only allow one photo to be uploaded? Photos Model has Many to One relationship with Profile and it must allow more than one photo to be uploaded to a profile. What must I do to solve the problem?

I just reset migration, deleted two tables in the MySQL database and did the migration again. I found out that the first time I successfully uploaded one or more photos at once to a profile, it worked as I expected. But after that it does not allow me to upload any more photo to the profile in admin “inlines” form.

I’m just curious - why are you specifying the to_field attribute in the Photos class and the fk_name in PhotosInline? Do you have multiple ForeignKeys in these models?

I’m probably more concerned about the to_field in the ForeignKey in Photos. Quoting directly from the docs:

By default, Django uses the primary key of the related object. If you reference a different field, that field must have unique=True.

And even though the OneToOneField is created within the database with a unique constraint, there’s no requirement that the primary key of that table be the same as the OneToOne key value.

My guess then is there’s something happening with those specifications causing some type of “confusion” within the ORM.

I’d at least give it a try it without those specifications.

Thanks for taking your time to answer my question. I want to use user_id in Profile table as a key that Photos table links to, as each user has one profile and each profile can have more than one photo. If I don’t specify to_field=“user” in the model Photos, Django would take the primary key id of Profile as reference of a foreign key. In the inline class PhotosInline, I have to specify “fk_name= ‘user’” because Django needs to know what field of Profile table the foreign key “user” of Photos table links to. Otherwise, Django just takes the profile id and inserts it into the user field of Profile table, and this is not what I want. After specifying “fk_name= ‘user’” in the inline class PhotosInline, it works as I expect as I see that the correct user’s id is inserted into the Profile’s user field, not the profile id. However, that limits the admin’s ability to upload photo more than once. As long as there is any photo belonging to a user in profile, Django prevents the admin to add any more photo to that user in Profile. I think Django thinks user is a unique field, which is correct in Profile table, but not unique Photos table. How can I tell Django that the foreign key user in Photos table is not unique and Django must allow multiple images to be uploaded for a user in Profile?

I have no problem when adding more photos to a specific user in profile in views I create outside admin, but in the admin I run into this problem.

I use MySQL database to store data and inspect data in the database in there to see how Django works. I have attempted to put print statement in files in Django’s core scripts in “django\forms” to trace the cause, but as soon I put a print statement or a new variable in there, the server throws an error “TabError: inconsistent use of tabs and spaces in indentation”.

KenWhitesell OneToOne is reference to the User table, and user field of of Profile is not primary key and that’s why I have to specify the “to_field=‘user’”, else Django takes profile_id as a reference right?

1 Like

Actually, it is what you want.

I’m not sure why you’re thinking you need to do it the way you’re doing it, but you don’t.

If the Photos are supposed to have a ForeignKey to the profile, then it should reference the primary key of the profile. If the Photos are supposed to have a ForeignKey to the User object, then it should be specified as having a ForeignKey to User, and not to Profile.

I could easily get around the problem by that way, but I don’t because I want to know how Django works and I want it to work the way I want. I did that because Profile and Photos belongs the same user, and later without having to filter Profile Model to get user’s id. Otherwise, I named “user” field in Photos table “profile”. My point here is to learn how manipulate Django to work the way I want.

Nope, you really don’t want to take that approach, unless you want to spend a lot of time digging into the internals and overriding or patching core.

You’re going to find that working with Django is a whole lot easier and more reliable than working against Django.

Or, as I frequently say, “Don’t Fight The Framework”.

Sure, you can do whatever you want with it - that’s the beauty of the open source model. However, as the saying also goes, “if you break it, you get to keep both pieces”. There are reasons why Django has evolved the way it has, and it works. But it is opinionated with how it works and really does expect things to be done in a certain way.

I don’t try to modify the Django’s core scripts or fight against the Framework, but I would like to know why it works that way, and if there is a way to make Django work the way I want without having to modify the framework, as I am new to the framework and still need to learn a lot to be good at Django. If that is the limitation of the framework, then I have to accept it and have to find a way to get around it. I posted the question because I thought Django offers developers a way to make the framework to work the way I want, and just because I thought someone else out there can show me the way to do that, I decided to post a question ask for help.
Honestly, I thought Django offers many cool built-in features that developers don’t to spend much time to build a website, and I want to take advantage of that. For my database design, I plan that I will add users’ Photo Album and blog that will could display photos of the users, and I don’t want the database server to do unnecsssary work to retreive the correct photos of specified users. I think it’s best for performance, extensibility, and flexibility when more features added to the website that need to use the users’ photos in the future because other features will not have to depend on the Profile table find out which photos a specified user owns. It matters when a website has millions of profiles and each day it has serve millions of requests. I don’t see why I should not try to eliminate the unaccessary work that database server will have to do if I can foresee the waste of the database server’s resource.
I respect your opinions and really appreciate your time. Neither you nor I am wrong right here, it’s about the goal we want to achieve when we sit down to design a database, and when normalize it we try to optimize it in a way we think best for our use cases not only at the present, but also for the future of the website.

Thanks again for spending your valuable time helping others

So then design your database to do this.

If Photos are supposed to relate to the User object (have the PK of a User), then make it a ForeignKey to User, not the Profile.

But beyond that, for any reasonable scale of work you’re going to be doing with this, you’re not adding “unnecessary work” - at least not to any detectable level.

10,000,000 requests per day is about 116 / second. PostgreSQL is going to handle that without breaking a sweat. (We have one database server writing data at the rate of 960 rows per second, 24x7. We have another sustaining a query rate of close to 1200 requests per second on a consistent basis. Granted, that one is an 8-core system where the entire database is memory resident.)

Your issues scaling to that size are not going to be PostgreSQL-related.

very helpful while using the inline form got same issues but using fk_name , problem is solved