2

I've found several solutions for doing this on the admin page or dynamically filtering using javascript based on another field, but I can't seem to piece the thoughts on those topics together to fix what I want.

I have the following:

  • a custom user model
  • a model, call it sunshine, which has the custom user model as a foreign key (eventually this will be many-to-many, but that's a whole different animal)
  • a model, call it ray, which has sunshine as a foreign key

I want:

  • A form for the logged in user (not the admin) to add a ray where the only options, on pageload, for sunshine are the sunshines related to the logged in user

Code:

Models.py:

    class SunshineUser(AbstractBaseUser):
        email = models.EmailField(
            verbose_name='email address',
            max_length=320, 
            unique=True
            )

        USERNAME_FIELD = 'email'

        name = models.CharField(max_length=150)

        is_active = models.BooleanField(default=True)

        is_admin = models.BooleanField(default=False)

        REQUIRED_FIELDS = ['name']

        objects = SunshineUserManager()

        def get_full_name(self):
            # The user is identified by their email address
            return self.email

        def get_short_name(self):
            # The user is identified by their name
            return self.name

        def __str__(self):
            return self.email

        def has_perm(self, perm, obj=None):
            return True

        def has_module_perms(self, app_label):
            return True

        @property
        def is_staff(self):
            return self.is_admin

    class Sunshine(models.Model):
        user = models.ForeignKey(settings.AUTH_USER_MODEL)
        label = models.CharField(max_length=150)
        SUNSHINE_TYPES = (
            ('R', 'Rain'),
            ('SH', 'Shine'),
            ('C', 'Clouds')
        )
        sunshine_type = models.CharField(max_length=2, choices=METER_TYPES)
        POSSIBLE_UNITS = (
            ('CCF', 'Hundreds of Cubic Feet'),
            ('GAL', 'Gallons')
        )
        units = models.CharField(max_length=3, choices=POSSIBLE_UNITS)

        def get_full_name(self):
            return self.label

        def get_short_name(self):
            return self.label

        def __str__(self):
            return self.label


    class Ray(models.Model):

        sunshine = models.ForeignKey(Sunshine)
        ray_amount = models.DecimalField(max_digits=15, decimal_places=5,
         validators=[MinValueValidator(0)])
        timestamp = models.DateTimeField()

        def get_full_name(self):
            return self.timestamp

        def get_short_name(self):
            return self.timestamp

        def __str__(self):
            return self.timestamp

Views.py:

def addray(request):
"""
processing for addreading
"""
if request.method == "POST":
    form = RayCreationForm(request.POST)
    if form.is_valid():
        form.save()
        # redirect, or however you want to get to the main view
        return HttpResponseRedirect('/personal/dashboard')
else:
    form = RayCreationForm()
    #form.sunshine.queryset = Sunshine.objects.filter(user_id=request.user.id)

return render(request, 'personal/addray.html', {'form': form})

Forms.py:

All I have right now is a basic form, because I've tried the commented out line under else in the views and a few other things and nothing has worked.

class RayCreationForm(forms.ModelForm):
class Meta:
    model = Ray
    fields = ['sunshine', 'ray_amount', 'timestamp']
ceaess
  • 68
  • 4

1 Answers1

2

In else, instead of the commented out line, you can try:

form.fields['sunshine'].queryset = Sunshine.objects.filter(user_id=request.user.id)

Other ways of filtering an initial queryset in a ModelChoiceField are shared here: https://stackoverflow.com/a/5329761/232649

Community
  • 1
  • 1
Pratyush
  • 5,108
  • 6
  • 41
  • 63