Home > Net >  How Can I query Django Models with Foreign and OneToOneFields for Field Values
How Can I query Django Models with Foreign and OneToOneFields for Field Values

Time:09-20

I have the following Django Models in my project: Event, Ticket, Pin and Guest so How can I query these tables in order to get the name of an Event Name the logged in guest user has registered for . Below are my code. My Models:

class Event(models.Model):
event_name = models.CharField(max_length=100)
date = models.DateField(auto_now_add=False, auto_now=False, null=False)
event_venue = models.CharField(max_length=200)
event_logo = models.ImageField(default='avatar.jpg', blank=False, null=False, upload_to ='profile_images')
added_date = models.DateTimeField(auto_now_add=True)

def __str__(self):
    return f"{self.event_name}"

#Prepare the url path for the Model
def get_absolute_url(self):
    return reverse("event_detail", args=[str(self.id)])

#Ticket Model
class Ticket(models.Model):
    event = models.ForeignKey(Event, on_delete=models.CASCADE)
    price = models.PositiveIntegerField()
    category = models.CharField(max_length=100, choices=PASS, default=None, blank=True, null=True)
    added_date = models.DateField(auto_now_add=True)

def __str__(self):
    return f"{self.event} "

#Prepare the url path for the Model
def get_absolute_url(self):
    return reverse("ticket-detail", args=[str(self.id)])

def generate_pin():
    return ''.join(str(randint(0, 9)) for _ in range(6))

class Pin(models.Model):
    ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE)
    value = models.CharField(max_length=6, default=generate_pin, blank=True)
    added = models.DateTimeField(auto_now_add=True,  blank=False)
    reference = models.UUIDField(primary_key = True, editable = False, default=uuid.uuid4)
    status = models.CharField(max_length=30, default='Not Activated')

#Save Reference Number
def save(self, *args, **kwargs):
     self.reference == str(uuid.uuid4())
     super().save(*args, **kwargs) 

def __unicode__(self):
    return self.ticket

class Meta:
    unique_together = ["ticket", "value"]

def __str__(self):
    return f"{self.ticket}"

def get_absolute_url(self):
    return reverse("pin-detail", args=[str(self.id)])

class Guest(models.Model):
    guest_name = models.OneToOneField(User, on_delete=models.CASCADE, blank=True) 
    pin = models.CharField(max_length=6, default='No Pin', blank=True)


def __str__(self):
    return f"{self.guest_name}" 

I am really confused on how to do this query. I have tried guest_event = Pin.objects.filter(guest__guest_name__icontains=request.user) but no way because I thinking of that .get() is the way out but can't figure it out, so someone should please help, even if it is to restructure the database for me to get solutions. Thanks

CodePudding user response:

You don't have FK to connect guest table with other tables, pin in Guest tab is a CharField, if you change it to FK field, you might be able to query it depending on your table schema

CodePudding user response:

Thanks @Vaibh Vaibhav lodha, your comment gave me an idea on how to figure it out and it worked. Here is how I have restructured my guest model:

class Guest(models.Model):
    guest_name = models.OneToOneField(User, on_delete=models.CASCADE, blank=True) 
    ticket = models.OneToOneField(Ticket, on_delete=models.CASCADE, blank=True) 


    def __str__(self):
        return f"{self.guest_name}" 

and in the views I used pin = request.session['pin'] to set the PIN value as the session and received it in the register_guest view pin = request.session.get('pin') and from there I have been able to verify the PIN value from session with the one in PIN model through a try and except DoesNotExist as shown below:

try:
    pin_detail = Pin.objects.get(value = pin)
except Pin.DoesNotExist:
    messages.error(request, 'PIN Does Not Exist')
    return redirect('pin-activation')
else:
    #Guest User Registration Form
    form = GuestUserForm() 
    page_title = "Festival Registration"
    if request.method == 'POST':
        form = GuestUserForm(request.POST) 
        #Check if Form contains valid data
        if form.is_valid():
            
            #Save the Guest User Form to get an instance of the user
            new_user = form.save()
            #Create A New Guest with his PIN
            Guest.objects.create(guest_name=new_user, ticket=pin_detail.ticket) 
            #Filter and update PIN
            Pin.objects.filter(value=pin).update(status='Activated')
            #Delete the PIN Session from the requet
            del request.session['pin']
            #Send User Message
            messages.success(request, 'Registered Successfully. Login')
            return redirect('user-login')
    else:
        form = GuestUserForm()
        
    context = {
        'form':form,
        'page_title':page_title,
    }
    return render(request, 'user/register.html', context)

And this is how I saved the Event name in the guest model using the create query: Guest.objects.create(guest_name=new_user, ticket=pin_detail.ticket) For me to get the Event Name I used pin_detail.ticket since pin_detail got to use .get() method in the query, then I also used the PIN attribute (ticket) from the query to get the event ticket associated with the PIN.

To get the Logged in Guest User Event I did the following in my index view:

try:
    guest_user = Guest.objects.get(guest_name = request.user)
    guest_event = guest_event.ticket
except Guest.DoesNotExist:
    messages.error(request, 'Guest Does Not Exist')
    return redirect('user-login')
else:
    context = {
       
        'guest_event':guest_event,
    }
    return render(request, 'user/profile.html', context) 

I stand to be corrected if I did not solve the issue using the best approach. Thanks

  • Related