How to add a new record with a guest (anonymous) user in Django

Viewed 1674

I am a beginner in Django and I am very need your help.

Part of code:

models.py

from django.contrib.auth.models import User

class Author(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    department = models.CharField(max_length=200)

    def __str__(self):
        return self.user.username

class hardware(models.Model):
    hostname = socket.gethostname()
    login_username = getpass.getuser()
    user = User.username

    hardware_name = models.CharField(max_length=20)
    order_no = models.CharField(max_length=10)
    price = models.DecimalField(max_digits=5,decimal_places=2)
    confirm = models.BooleanField(default=False)
    login_user = models.ForeignKey(Author, on_delete=models.CASCADE)
    computer_login_user = models.CharField(max_length=10,default=login_username)
    computer = models.CharField(max_length=30,default=hostname)


    def __str__(self):
        return self.order_no

views.py

def get_author(user):
    qs = Author.objects.filter(user=user)
    if qs.exists():
        return qs[0]
    return None

def new_record(request):
    form = OrderForm(request.POST or None, request.FILES or None)
    if form.is_valid():
        author = get_author(request.user)
        form.instance.login_user = author
        form.save()
        return redirect(all_records)

    context = {
        'form': form
    }
    return render(request, 'orders/form.html', context)

I will try to explain my problem briefly.

Computers are in public places (productions) and anyone can add new record. That why in the table is info about hostname, who is login on computer and login user.

So it works well when the user is logged in to the system, but there is a problem when a new record tries to add an unlogged user (guest). Is an error "'AnonymousUser' object is not iterable". I know that request.user is empty now.

Ok, Now questions...

How to add "guest" user and add it if noone is login?? How to add a new record if the user is not logged in??

I am sorry for very long post and Thanks for all suggestions.

2 Answers

So, if I understand correctly, you can do this a few ways:

  1. The easiest way is to simply set the login_user field nullable and blank or,
  2. Create a "guest user" and "guest author" in your Django database that is not active (is_active is set to False so they can't log in) and all anonymous users are assigned that User and Author instance the database.

As mentioned, the simplest method would be just to set the login_user field as nullable and blank, like such:

login_user = models.ForeignKey(Author, on_delete=models.CASCADE, blank=True, null=True)

And if your get_author() returns None, then simply leave that column blank, though this might affect other parts of your application if an Author or User object is required elsewhere.

Another way to do it in your get_author() method using a "guest" user:

def get_author(user):
    if user.is_anonymous:
        guest_user = User.objects.get(username="guest") # or whatever ID or name you use for the placeholder user that no one will be assigned
        guest_author = Author.objects.get_or_create(user=guest_user)
        return guest_author
     else:
        return Author.objects.get(user=user) 

In this option, you'd need to set your department field in Author to blank and null or set a default like:

class Author(models.Model):
      user = ...
      department = ...(..., default="none")

or

 class Author(models.Model):
       user = ...
       department = ...(..., blank=True, null=True)

Yet another option might be to create a new "guest" user for each action:

import random
import string

def randomString(stringLength):
    letters = string.ascii_letters
    return ''.join(random.choice(letters) for i in range(stringLength))

def get_author(user):
        if user.is_anonymous:
            random_username = f"{randomString(10)}_guest"
            random_email = f"{randomString(5)}_guest@example.com"
            guest_user = User.objects.create(username=random_username, is_active=False, email=random_email...) 
            guest_author = Author.objects.create(user=guest_user, department="none")
            return guest_author
         else:
            return Author.objects.get(user=user)

Thank you for your help and time. I chose the second solution after little change.

def get_author(user):
    if user.is_anonymous:
        guest_user = User.objects.get(username="guest") # or whatever ID or name you use for the placeholder user that no one will be assigned
        qs = Author.objects.filter(user=guest_user)
        if qs.exists():
            return qs[0]
        return None
     else:
        qs = Author.objects.filter(user=user)
        if qs.exists():
            return qs[0]
        return None

Now is little better and working well. When I use exactly your method was little mistake: "ValueError: Cannot assign "(<Author: guest>, False)": "hardware.login_user" must be a "Author" instance."

So, anyway thank you again.

Related