Model for Article - Front Page or Not

Hello, as my “newspaper/blog” takes shape, I’ve reached the point, where as the “editor” coughs I would like the option to prioritize what is displayed on the front-page.

Presently, it’s first come, first served on the main page. (i.e all the articles are first in first out), whereas I might want to select something in the middle of the articles and display that as a “sticky”

My initial thought was bung a boolean field on the model : front_page. However, I’ve resisted that impulse for now, for better ideas.

Ideas on the model would be welcome. I’m just wondering how in the “real-world” that is done.

My model, presently :

class Article(models.Model):
   
    class Categories(models.TextChoices):
        NEWS = 'NW', _('News')
        TECH = 'TC', _('Technology')
        FASHION = 'FS', _('Fashion')
        MUSIC = 'MS', _('Music')
        
         

    category  = models.CharField(
        max_length=2,
        choices=Categories.choices,
        default=Categories.NEWS,
    )     
    
    title = models.CharField(max_length=30)
    author =  models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
    date_created = models.DateTimeField(auto_now_add=True)
    intro = models.CharField(max_length=100) #lede
    content = models.TextField() #don't repeat the lead here
    #image = models.ImageField(default='default.jpg',upload_to='profile_pics')
    image = models.ImageField(blank='true',upload_to='profile_pics/')
    
    

    def __str__(self):
          return f'Author : {self.author.username}'
    
    def get_absolute_url(self):
        #return reverse('article_detail', args=[str(self.id)])
        return reverse('index')  
       

    def resize_image(self):
        if self.image :  #image can be blank
            try : 
            
                img = Image.open(self.image.path)
                if (img.height > 300) or (img.width > 300) :
                    output_size = (300,300)
                    img.thumbnail(output_size)
                    img.save(self.image.path)
            except Exception as e :
                print(f'failed to resize image' ,str(e)) 
         

    def save(self): #def save(self, *args, **kwargs):
        #author = self.request.user
       
        super().save()  
        
        self.resize_image()  #note to self : seems a bit hacky here, too. i.e. calling save 1st

        
        print('saving model')      

Speaking from personal experience, these projects typically need more curation than just having a boolean or some other field on a model can help with.

Assuming, you have a set format or blocks on your homepage, you may want to create a homepage model (we called them “Section Fronts” in one of the original Django websites aka EllingtonCMS). This model tracks which articles should show up in which section or block.


class SectionFront(models.Model):
    lead_article = models.ForeignKey("Article",  ...)
    secondary_article = models.ForeignKey("Article", ...)
    block0_article = models.ForeignKey("Article", ...)
    block1_article = models.ForeignKey("Article",  ...)
    block2_article = models.ForeignKey("Article",  ...)
    block3_article = models.ForeignKey("Article",  ...)

If you want to get fancy, add a published = DateTimeField() to your SectionFront article model and you can schedule what your homepages for future dates. You just need to update your View to show the latest() SectionFront by date and filter out published__gt=now() and you should be good to go.

I would also add a name and slug field to the model in case you want to curate more than just your homepage.

Thanks Jeff, good ideas.

I’m working through it currently, I’m using css-grid for layout.

My main grid is 12 cols. I use spans for columns on each row.

On my front-page I’m currently working off the current cols/spans, per row
2 x 6
4 x 3
2 x 6
1x 3 and 1x9

which looks pretty good, to break up the monotony. I have only 1 media qry, currently. Everything is one column on small device, on portrait, it’s what you see below.

I can style it later, but what i’m interested in is how this will hang together at the back-end, and how to loop it front-end. It’s not exactly a simple for loop. So I’m thinking in this scenario, I’d have 4 contexts passed back to the template via the view. (although I have one model for articles). To loop this in the template, I’d have the following sequence of buckets for each article :

row 1 - 2 articles
row 2 - 4 articles
row 3 - 2 articles
row 4 - 2 articles

Ideally, I’d like one context, and front-end algorithm to sort it out. otherwise, everytime I change a layout, I’d need different context to be supplied to the front-end.

HTML

 <div class="section">  
            <div class="container"> 
                <div class="columns"> <!-- 12 col grid on portrait-->
                    
                    <div class="span_6">  
                       <!--  <div class="box border"> -->
                            <div class="box border">#1 orem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.

                            </div>
                            
                    </div>

                    <div class="span_6">  
                        <!--  <div class="box border"> -->
                             <div class="box border">#2 orem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</div>
                             
                     </div>
                    
                </div>
                <div class="columns"> <!-- 12 col grid on portrait-->
                    
                    <div class="span_3">  
                       <!--  <div class="box border"> -->
                            <div class="box border">#1 orem Ipsum is simply dummy text of the printing and typesetting industry. </div>
                            
                    </div>

                    <div class="span_3"> 
                        <!--  <div class="box border"> -->
                             <div class="box border">#2 orem Ipsum is simply dummy text of the printing and typesetting industry. </div>
                             
                     </div>
                     <div class="span_3">  
                        <!--  <div class="box border"> -->
                             <div class="box border">#3 orem Ipsum is simply dummy text of the printing and typesetting industry. </div>
                             
                     </div>
                     <div class="span_3">  
                        <!--  <div class="box border"> -->
                             <div class="box border">#4 orem Ipsum is simply dummy text of the printing and typesetting industry. </div>
                             
                     </div>
                    
                </div>
                <div class="columns"> <!-- 12 col grid on portrait-->
                    
                    <div class="span_6">  
                       <!--  <div class="box border"> -->
                            <div class="box border">#1 orem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</div>
                            
                    </div>

                    <div class="span_6"> 
                        <!--  <div class="box border"> -->
                             <div class="box border">#2 orem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</div>
                             
                     </div>
                    
                </div>
                <div class="columns"> <!-- 12 col grid on portrait-->
                    
                    <div class="span_3">  
                       <!--  <div class="box border"> -->
                            <div class="box border">#1 orem Ipsum is simply dummy text of the printing and typesetting industry. </div>
                            
                    </div>

                    <div class="span_9"> 
                        <!--  <div class="box border"> -->
                             <div class="box border">#2 orem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.</div>
                             
                     </div>
                    
                </div>
            </div>
        
        </div>

1 Like

If anyone is interested in this, I have a better solution, I’m working through. When I’ve finished it, I’ll probably do a blog post. In a nutshell, I’ve simplified the css, and worked out the model at the back-end. Stay tuned amigos!

Hopefully, I’ll cover how to work with css grid and django, and make them play nice.

1 Like