0

AIM

I am attempting to set the Alarm.username to the username of the currently logged in User. The problem is identical to another query, although my code is a little different in that I extract location details for each Alarm object.

How,and where, do I integrate the line: username=User.objects.get(username=self.request.username) in my code?

ERROR

Request Method: POST
Request URL:    http://jqlc3gdp.apps.lair.io/login/set_alarm/
Django Version: 2.0
Exception Type: AttributeError
Exception Value:    
'WSGIRequest' object has no attribute 'username'
Exception Location: /mnt/project/weather_alarm/views.py in get_user_timezone, line 94

CODE

Models.py

class User(models.Model):
    """ Model representing each User """
    username = models.CharField(max_length=20, unique=True)
    password = models.CharField(max_length=30, validators=[MinLengthValidator(8)])
    email = models.EmailField(max_length=254)
    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=20)


class Alarm(models.Model):
    """ Model representing each Alarm """
    alarm_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    username = models.ForeignKey(User, on_delete=models.CASCADE, null=True)         # null=True is TEMP
    timezone = models.CharField(max_length=30)
    city = models.CharField(max_length=30)
    country = models.CharField(max_length=30)
    time = models.DateTimeField()
    temp_conditional = models.BooleanField()
    surf_conditional = models.BooleanField()
    temp_max = models.FloatField(blank=True, null=True)
    temp_min = models.FloatField(blank=True, null=True)
    surf_max = models.FloatField(blank=True, null=True)
    surf_min = models.FloatField(blank=True, null=True)

Forms.py

class SetAlarmForm(ModelForm):
    ...    
    class Meta:
        model = Alarm
        exclude = ['username', 'timezone', 'city', 'country']

Views.py

class AlarmCreateView(LoginRequiredMixin, CreateView):
    model = Alarm
    form_class = SetAlarmForm
    template_name = 'weather_alarm/set_alarm.html'
    success_url = reverse_lazy('weather_alarm:confirm-alarm')
    login_url = "/login/"

    def form_valid(self, form):
        self.get_user_location(form)
        return super().form_valid(form)

    def get_user_location(self, form):
        """ Function to get User's location from IP and create Alarm object """
        ...
        alarm_object = Alarm.objects.create(
            alarm_id=uuid.uuid4(),
            username=User.objects.get(username=self.request.username),
            timezone=user_timezone,
            city=location.raw['address']['city'],
            country=location.raw['address']['country'],
            time=form.cleaned_data['time'].astimezone(pytz.timezone(user_timezone)),
            temp_conditional=form.cleaned_data['temp_conditional'],
            surf_conditional=form.cleaned_data['surf_conditional'],
            temp_max=form.cleaned_data['temp_max'],
            temp_min=form.cleaned_data['temp_min'],
            surf_max=form.cleaned_data['surf_max'],
            surf_min=form.cleaned_data['surf_min'],
        )
        alarm_object.save()
Darcy
  • 575
  • 2
  • 8
  • 21
  • `self.request.username`, first of all the request object doesn't have the attribute called `username`, hence your error. Also you're using ForeignKey for the username field in Alram Model. – user2906838 Aug 07 '18 at 01:58

1 Answers1

1

It should be self.request.user.username:

username = User.objects.get(username=self.request.user.username)

Or since request.user already contains current user object better to use:

username = self.request.user
neverwalkaloner
  • 46,181
  • 7
  • 92
  • 100
  • I tried that and get the following error: `Exception Type: DoesNotExist. Exception Value: User matching query does not exist.` – Darcy Aug 07 '18 at 02:13
  • 1
    @ycrad did you set `AUTH_USER_MODEL`? https://docs.djangoproject.com/en/2.0/topics/auth/customizing/#substituting-a-custom-user-model – neverwalkaloner Aug 07 '18 at 02:14
  • @Thomas Thanks for edit, but can you please explain why you remove `username = self.request.user` part? – neverwalkaloner Aug 07 '18 at 02:16
  • 1
    I explained in the edit message: `username` is a CharField, `self.request.user` is a LazyLoaded User object. Assigning one to the other relies on implicit conversion through `Model.__unicode__()` and should not be considered stable, is definitely not something you should be teaching new django programmers. I've personally had a lot of trouble with LazyLoad user objects with the ORM in the past. Stick to assigning strings to CharFields and you won't get any weird, hard to debug issues in the future. – Thomas Aug 07 '18 at 02:22
  • 1
    @Thomas Thank you. But username is ForeignKey in Alarm model, not CharField. So assigning shouldn't give any problem in this situation. Or I missed something? – neverwalkaloner Aug 07 '18 at 02:27
  • 2
    You are correct, I was the one missing something. In which case, your first suggestion is the wrong one, and the second one is right. – Thomas Aug 07 '18 at 03:38
  • Thanks for the feedback. I amended to `username=self.request.user` as suggested, but am getting the following error: `ValueError: Cannot assign ">": "Alarm.username" must be a "User" instance.` Is it because I haven't set up `AUTH_USER_MODEL` as suggested? – Darcy Aug 08 '18 at 00:12
  • 1
    @ycrad yes, by default Django using builtin User model. – neverwalkaloner Aug 08 '18 at 01:54