-1

So i have a model called Partner. A business is a partner. I have a foreignkey field who takes self as a parameter to create choices. What i want to do is to go through all the created partners and filter out ones that are parent companies. I was thinking of having a boolean that says is_parent. How do i go about this can i search for the boolean in the database and create a choicefield or something with it so i can get a list of parent companies?

What i am trying to do is filter the parents and either make the filtered objects into a choicefiled or make a second model with it so i can offer the choice of selecting the parent.

I have tried to filter through my result but that did not work as expected.

from django.db import models
from django.urls import reverse

from model_utils import Choices
from model_utils.fields import StatusField
from model_utils.models import StatusModel, TimeStampedModel
from phone_field import PhoneField
from addresses.models import Address
from 

common.utils import COUNTRIES





class Industry(models.Model):
    """ Business Industry model """
    name = models.CharField(max_length=100)

    class Meta:
        verbose_name = 'Industry'
        verbose_name_plural = 'Industries'
        ordering = ('name',)

    def __str__(self):
        return '%s' % self.name


class PartnerType(models.Model):
    name = models.CharField(blank=False,
                            help_text="Name of the role or function", max_length=64,
                            verbose_name="Partner Type", )

    class Meta:
        verbose_name = 'partner type'
        verbose_name_plural = 'partner types'

    # TO STRING METHOD
    def __str__(self):
        return '%s' % self.name


class Partner(TimeStampedModel, StatusModel):

    INVOICE_METHOD_CHOICE = (
        ("PAPER", "Paper"),
        ('EMAIL', 'Email'),
    )

    LEGAL_STRUCTURE_CHOICES = (
        ('CORPORATION', 'Corporation'),
        ('LLC', 'LLC'),
        ('SOLE PROPRIETOR', 'Sole Proprietor'),
        ('PARTNERSHIP', 'Partnership'),
    )

    PARTNER_OFFICE_CHOICES = (
        ('HEADQUARTERS', 'Headquarters'),
        ('DIVISION', 'Division Office'),
        ('SITE', 'Site'),
        ('DC', 'Distribution Center'),
    )

    ADDRESS_TYPES = (
        ('Billing', 'Billing'),
        ('Shipping', 'Shipping'),
        ('Physical', 'Physical'),
    )

    STATUS = Choices('Active', 'Inactive', 'Credit Hold',)
    name = models.CharField(blank=True, max_length=100, verbose_name='Account Name', )
    office_level = models.CharField(
        choices=PARTNER_OFFICE_CHOICES, max_length=50, blank=True,)
    trade_name = models.CharField(blank=True, max_length=100, verbose_name='Trade Name', )
    logo = models.ImageField(default='default.jpg', upload_to='partners/logos')
    industry = models.ForeignKey(
        Industry,
        blank=True,
        help_text="Industry",
        null=True,
        on_delete=models.SET_NULL,
        related_name="partners_industry", )
    csp_rank = models.IntegerField(blank=True,null=True )
    partner_types = models.ManyToManyField(PartnerType)
    account_number = models.IntegerField(blank=True, editable=True,default=0)
    vendor_number = models.CharField(blank=True, help_text="TEAZZERS account number with the partner", max_length=20,)
    phone = PhoneField(blank=True, null=True, )
    fax = PhoneField(blank=True, null=True, )
    email = models.EmailField('main email address', blank=True)
    ap_email = models.EmailField('AP email address', blank=True)
    ar_email = models.EmailField('AR email address', blank=True)
    website = models.URLField('Website', blank=True)
    description = models.TextField(blank=True)
    total_units = models.PositiveIntegerField(blank=True, null=True, verbose_name='Total units',
                                            help_text='How many locations does this organization have?')



    parent = models.ForeignKey(
        'self',
        blank=True,
        help_text="Parent Company name (if necessary)",
        null=True,
        on_delete=models.CASCADE,
        max_length=200
        )
    # if total_units > 0:
    #     status = 'Parent'
    #
    # if status == "Parent":
    #     parent = models.ForeignKey(
    #     'self',
    #     blank=True,
    #     help_text="Parent Company name (if necessary)",
    #     null=True,
    #     on_delete=models.CASCADE,
    #     related_name="partners_partner", )

    w9 = models.BooleanField(default=False, verbose_name='IRS Form W-9',
                             help_text='Have we received a completed IRS Form W-9?',)
    legal_structure = models.CharField(
        choices=LEGAL_STRUCTURE_CHOICES, max_length=50, blank=True,
        help_text='How is the business structured?',)
    ein = models.CharField(max_length=9, blank=True, default='', verbose_name='Federal Employer Identification Number')
    duns = models.CharField(max_length=13, blank=True, default='', verbose_name='Dun & Bradstreet (DUNS) Number')
    gln = models.CharField(max_length=13, blank=True, default='', verbose_name='GLN (GS1 Global Location Number)')
    insurance = models.BooleanField(default=False, verbose_name='Insurance',
                                    help_text='Have we received liabilty insurance paperwork?',)
    insurance_end_date = models.DateField(blank=True, null=True, verbose_name='Insurance End Date',
                                          help_text="When does insurance on file end? "
                                                    "Please use the following format: <em>YYYY-MM-DD</em>.")
    insurance_files = models.FileField(upload_to='partners/insurance', blank=True,
                                       verbose_name='Current Insurance Paperwork')
    sales_tax = models.BooleanField(default=False, verbose_name='Sales Tax Paperwork',
                                    help_text='Have we received Uniform Sales & Use Tax Certificate?',)
    sales_tax_files = models.FileField(upload_to='partners/sales_tax', blank=True,
                                       verbose_name='Current Insurance Paperwork')
    invoice_method = models.CharField(
        choices=INVOICE_METHOD_CHOICE, max_length=64, default='paper')
    start_date = models.DateField(blank=True, null=True, verbose_name='Active Since',
                                  help_text="When we begin doing business? Please use the"
                                            " following format: <em>YYYY- 
    MM-DD</em>.")
    address_type = models.CharField(
        max_length=20, choices=ADDRESS_TYPES,blank=True)
    street1 = models.CharField(
        'Street Line 1', max_length=100, blank=True)
    street2 = models.CharField(
        'Street Line 2', max_length=100, blank=True)
    city = models.CharField('City', max_length=100, blank=True)
    state = models.CharField('State', max_length=100, blank=True)
    postcode = models.CharField('Post/Zip-code', max_length=32, blank=True)
    country = models.CharField(
        max_length=3, choices=COUNTRIES, blank=True)

    def __str__(self):
        # return self.city if self.city else ""

        return '%s' % self.full_address

    @property
    def full_address(self):
        return ' %s %s %s %s %s' % (self.street1, self.street2, self.city, 
    self.state, self.postcode)

    def get_complete_address(self):
        address = ""
        if self.street1:
            if address:
                address += ", " + self.street1
            else:
                address += self.street1
        if self.street2:
            if address:
                address += ", " + self.street2
            else:
                address += self.street2
        if self.city:
            if address:
                address += ", " + self.city
            else:
                address += self.city
        if self.state:
            if address:
                address += ", " + self.state
            else:
                address += self.state
        if self.postcode:
            if address:
                address += ", " + self.postcode
            else:
                address += self.postcode
        if self.country:
            if address:
                address += ", " + self.get_country_display()
            else:
                address += self.get_country_display()
        return address

    primary_address = models.ForeignKey(
        Address,
        blank=True,
        help_text="Primary Address",
        null=True,
        on_delete=models.SET_NULL,
        related_name="partners_industry")
    # MANAGERS
    parent_list = list()
    # META CLASS
    class Meta:
        verbose_name = 'partner'
        verbose_name_plural = 'partners'

    # TO STRING METHOD
    def __str__(self):
        return '%s' % self.name

    @property
    def full_name(self):
        return '%s %s' % (self.name, self.site_id)

    # SAVE METHOD

    def save(self, *args, **kwargs):
        super(Partner, self).save(*args, **kwargs)
        #self.account_number = self.pk + 1000

    # ABSOLUTE URL METHOD
    def get_absolute_url(self):
        return reverse('partners:detail', kwargs={'pk': self.pk})

    def get_delete_url(self):
        return reverse('partners:delete', kwargs={'pk': self.pk})

'''
zef
  • 1
  • 2

2 Answers2

0

Assuming you have some other model (not shown in your models.py above) for which you want to only have parent companies be available for selection, first define a callable:

parent_companies():
    return Partner.objects.exclude(parent=None).values_list('id', 'name')

Then use the callable for choices=:

class SomeModel(models.Model):
    some_company = models.ForeignKeyField(Partner, choices=parent_companies())
Dan Swain
  • 2,910
  • 1
  • 16
  • 36
  • So am I able to create another model using the contents from this list to give someone the choice of selecting from a dropdown menu? – zef Jul 16 '19 at 22:52
  • Yes, you could have another model that foreign keys to `Partner`: `partner = models.ForeignKeyField(Partner, ...)` – Dan Swain Jul 17 '19 at 00:30
  • If you're talking about restricting the choices for `partner` to just parent companies, then this might help: https://stackoverflow.com/a/5105092/5548239. I think that you could make `parent_companies` a callable that returns a set of two-tuples and use this set like so: `partner = models.ForeignKeyField(Partner, choices=parent_companies())`. I could re-work my answer if this is still not clear. – Dan Swain Jul 17 '19 at 13:11
  • Please post the relevant section of your `models.py` rather than just one field from a model. I can then re-work my answer. – Dan Swain Jul 17 '19 at 13:33
  • posted whole model. – zef Jul 17 '19 at 13:59
  • I updated my model please have a look when you can. – zef Jul 17 '19 at 17:36
0

this query will get you all the parent companies in all levels assume that we have a structure like that

  • 1 is parent of 3 and 4
  • 2 is a parent of 6 and 5
  • 3 is a parent of 9 and 10
  • 4 is a parent of 11 and 12
  • 6 has no sons
  • 5 is a parent of 7 and 8
  • 13 has no parent # parent = None

so (1, 2, 3, 4, 5) is a parent as every one has at least one son

parents = ModelName.objects.exclude(parent=None).values_list('parent', flat=True).annotate(count = Count('parent')).order_by('parent')

this return for you a list of ids for all parents you can get queryset of parents as below

parents_queryset = ModelName.objects.filter(id__in=list(parents))

note : parent means it already have at least one son

if you need to get with them the node which already doesn't have parent # parent is None and assume that it have no parent so it is a parent

new_parents_queryset = parents_queryset | ModelName.objects.filter(parent=None)
# this queryset is all the parents that have at least one son or the parents that have no parent 

here (1, 2, 3, 4, 5, 13) is the parents as 13 have no parent

  • @zef why you need to filter the parents only as any partner have a chance to be a parent i think you have to show all available partners in you Partner model – Mohamed Abd El-hameed Jul 16 '19 at 23:20